본문 바로가기

CS

유저 스택과 커널 스택

출처: https://kldp.org/node/73308

 

커널 스택이 궁금합니다. | KLDP

리눅스 커널 스택에 대해서 궁금합니다. 1.커널 스택은 프로세스마다 하나씩 생성되는 건가요 ? 2.커널 스택에는 어떤 정보가 들어가게 되나요 ? (얼핏 알기로는 해당 프로세스에 인터럽트가 걸

kldp.org

질문

1. 커널 스택은 프로세스마다 하나씩 생성되는가?

2. 커널 스택에는 어떤 정보가 들어가는가

 

3. 프로세스 하나는 4기가의 가상공간을 사용한다고 들었다. 이 중에서 0~3이 응용프로그램이고 3~4기가는 커널이 사용하는 공간인데 어떤 연관성이 있나??

답변:

1. 커널 스택은 프로세스마다 하나씩 생성됩니다.
일반적인 프로세스는 User Mode 스택과 Kernel Mode 스택을 각각 하나씩 가지고 있습니다.
User Mode에서 Kernel Mode로의 전환은 시스템호출이나 인터럽트가 발생하면 일어납니다.
즉, esp 레지스터는 프로세스가 User Mode이면 User Mode 스택의 top을 가리키다가
Kernel Mode로 전환이 되면 Kernel Mode 스택의 top을 가리킵니다.

 

2. Kernel Mode 스택은 적어도 다음 두 가지 목적으로 사용됩니다. 다른 사용처는 딱히 생각나지 않네요.
가. Kernel Mode로 전환된 프로세스는 언젠간 다시 User Mode로 되돌아가야 합니다.
따라서 User Mode로 전환하기 위해 필요한 정보 중 일부를 저장합니다. (일부는 다른 곳에 저장합니다.)


나. Kernel Mode에서 함수를 호출하게 되면 그 함수의 지역변수는 Kernel Mode 스택에서 할당됩니다. (User Mode에서 함수를 호출하면 지역변수가 User Mode 스택에 할당되는 것과 같습니다.)
참고로 80x86 아키텍처에서 커널 스택으로 할당된 공간의 크기는 8KB로 고정되어있습니다. 프로세스 생성 때 한번 할당되어 작아지지도 커지지도 않습니다. 따라서 커널에 있는 함수에서는 지역변수를 많이 할당하거나 재귀 함수 호출을 하면 좋지 않습니다.

 

3. 
커널은 주소 공간 3~4GB를 사용합니다. Kernel Mode 스택은 Kernel Mode에서만 사용되므로 커널 주소 공간에서 할당됩니다.
즉, User Mode 스택을 가리키는 esp 값을 읽어보면 0GB~3GB 사이의 값을 가지고 Kernel Mode 스택을 가르키는 esp 값을 읽어보면 3~4GB 사이의 값을 가지게 됩니다.

 

4. 기타

 

가. 프로세스의 User Address Space는 프로세스마다 각각 다르지만, Kernel Address Space는 모든 프로세스가 동일하게 봅니다. 즉, 프로세스 A와 프로세스 B의 특정 가상 주소 (예를 들면 0xa0001000) 은 서로 다른 물리 주소로 맵핑될 수 있습니다. 하지만 특정 커널 공간 주소 (예를 들면 0xc0001000) 는 모든 프로세스에서 동일한 물리주소로 맵핑됩니다.
이를 위해서 커널은 kernel master page table (swapper_pg_dir 변수가 가리킴)을 관리하고, 필요할 때마다 특정 엔트리를 kernel master page table에서 해당 프로세스의 page table에 복사를 합니다 -- 이런 작업은 Kernel Mode에서 페이지 폴트가 발생했을 때 페이지 폴트 핸들러가 수행합니다.

 

나. 시스템 호출, 인터럽트 핸들러, 커널 모듈 등은 임의의 프로세스의 context를 이용합니다. 예를 들어, 프로세스 A가 User Mode에서 수행되고 있을 때 timer interrupt가 발생하는 경우 Kernel Mode로 전환하여 timer interrupt service routine을 수행하게 되는데 이때 프로세스 A의 page table과 Kernel Mode 스택을 빌어 쓰게 됩니다.
Timer interrupt와 프로세스 A와는 별다른 연관이 없지만 interrupt 발생 시점에 프로세스 A가 CPU를 점유하고 있었기 때문에 부하가 큰 context switch 등을 따로 하지 않고 프로세스 A의 context를 그대로 이용하는 것입니다. 다만 커널 모듈 등이 기능의 일부를 따로 커널 스레드를 생성하여 구현한 경우라면 그 커널 스레드의 context를 사용하겠죠.


추가 답변

>1. 커널 스택은 프로세스마다 하나씩 생성되는 건가요?

커널은 프로세스가 생성될 때 0x2000(32비트), 0x4000(64비트) 크기의 스택 공간을 할당합니다.
만약 init 이란 프로세스와 ksoftirq/0 프로세스가 있다면 각각 0x2000 사이즈 스택을 사용합니다.(32비트 기준)

>2. 커널 스택에는 어떤 정보가 들어가게 되나요?

프로세스가 실행하는 스택 공간에는 다음 정보를 확인할 수 있습니다.
1) 스택 최상단 주소에는 thread_info 구조체가 위치합니다. 이 구조체에서 프로세스 세부 실행 정보를 확인할 수 있습니다.
thread_info 구조체는 아키텍처(ARM, x86) 마다 정보(필드)가 다릅니다.
2) 스택 최하단 주소
: 유저 프로세스이면 유저 공간에서 실행 중인 레지스터 정보를 볼 수 있습니다.
3) 스택 최하단 주소 -> 스택 최상단 주소 방향
: 함수를 호출할 때 프레임 포인터 레지스터와 스택 주소를 확인할 수 있습니다.
: 함수 지역 변수에 저장된 값을 확인할 수 있습니다.

 

출처: https://blog.daum.net/tlos6733/170

 

[Stack] linux kernel stack

작성자 : 박진범 메일 : jinb.park7@gmail.com :) Goal - linux kernel stack 관리에 대해 이해한다. - 특수한 kernel stack 에 대해 이해한다. - user space stack 과의 차이점을 이해한다. :) 커널 모드 프로세..

blog.daum.net

커널 모드 프로세스 스택 (kernel mode process stack, thread_info)

 

- x86 에서, 프로세스는 자신의 한 메모리 영역에 thread_info 구조체와 커널 모드 프로세스 스택을 함께 저장한다. 이 메모리의 영역의 길이는 보통 8kb 이다.  커널 모드 프로세스 스택은 유저 스택처럼, 쓰레드마다 할당된다.

 

- stack 과 thread_info 는 아래와 같이 배치되며, stack 은 thread_info 쪽으로 커진다.

  0x015fbff     stack

     ........               |

     ........               v

  0x015fa000   struct  thread_info

 

- thread_info->task ==> task_struct

 task_struct->stack ==> thread_info

 위와 같이 task_struct 와 thread_info 가 서로 연결되어 있다.

 

- 커널 모드 프로세스 스택의 할당은, 아래와 같은 함수 호출 구조 아래 이루어진다. 즉, 프로세스 생성 시 이루어진다. 

  시스템 콜에 의한 프로세스 생성 (fork*, clone, ..), 커널 쓰레드 생성 모두 내부적으로는 아래와 같은 순서로 호출된다.

  _do_fork() -> copy_process() -> dup_task_struct() -> alloc_thread_stack_node()

 

 alloc_thread_stack_node() 함수에서 실제로 커널 모드 프로세스 스택을 할당한다.

 

유저 모드 프로세스 스택 (user mode process stack)

 

- 유저 모드 프로세스 스택의 경우, 알다시피 가상주소로 매핑되어 사용된다. 즉, 물리적으로는 동적으로 다른 주소에 매핑된다는 뜻이다.

  task_struct->mm->mmap (vm_area_struct) 에 VMA 의 하나로써 매핑되는 것이다. 따라서 프로세스마다 동적으로 항상 다른 스택 주소 (물리적으로) 를 가질 수 있다.

 

- 유저 모드 프로세스 스택, 힙의 경우 메모리 관리 과정은, 프로세스 최초 생성될 때는 vma 만 세팅되고, 실제 특정 코드 실행하거나 특정 데이터 접근 시에 page fault 발생하면, 그 때 page 단위로 할당되는 것이다.

 

 프로세스에서 유저 영역의 힙, 스택에 대한 page 는 커널에서는 anonymous page 라고 부르는데, 이는 보통 file 과 연결되지 않는 page 를 의미하는 것이다. 

 힙, 스택 접근에 대해 page fault 발생하게 되면, 

  handle_pte_fault() -> do_anonymous_page() -> alloc_zeroed_user_highpage_movable() -> alloc_page_vma()  

  ==> 위 함수 호출로써,  해당하는 vma 에 맞는 page 를 할당하여 리턴해준다.

 

 

전체 커널 메모리 상에서  커널 모드 프로세스 스택의 위치

- alloc_thread_stack_node() --> alloc_kmem_pages_node(node, THREADINFO_GFP,  THREAD_SIZE_ORDER) 

 위 함수를 통해 커널 모드 프로세스 스택의 메모리를 할당하는데, kernel 에서 사용할 memory 이므로, ZONE_NORMAL 영역에 저장된다. 즉, 가상주소<->물리주소가 direct 매핑되어 있는 공간에 매핑된다. (ARM 의 경우 section mapping 되는 공간. 이 부분은 커널 초기화 시 이미 page table 이 확정되기 때문에 page fault 는 발생하지 않는다.)

 

 

가상매핑된 커널 스택 글

https://blog.daum.net/tlos6733/175

'CS' 카테고리의 다른 글

Pintos Project2: User Programs  (0) 2021.10.13
Virtual Memory  (0) 2021.10.07
Pintos project 1 Alarm clock, priority scheduling  (0) 2021.10.04
CPU 가상화  (0) 2021.10.04
커널 레벨 쓰레드와 유저 레벨 쓰레드  (0) 2021.10.02