Virtual Memory Layout
- Pint OS에서 가상 메모리는 2개의 영역으로 나뉜다.
- User Virtual Memory: 가상 주소 0부터 KERN_BASE(0x8004000000) 사이의 영역
- Kernel Virtual Memory: 가상 주소 KERN_BASE(0x8004000000) 이상의 영역
User Virtual Memory
유저 가상 메모리는 프로세스마다 할당된다. 커널이 한 프로세스를 다른 프로세스로 전환할 때, 페이지 테이블을 통해 유저 가상 주소 공간도 전환된다(Context Switching).구조체 thread는 프로세스의 페이지 테이블을 가리키는 포인터를 가지고 있다(curr_thread->pml4).
유저 프로그램은 오직 할당된 유저 가상 메모리에만 접근할 수 있다. 커널 가상 메모리에 접근하려고 하면 page_fault() 함수에 의해 page fault 에러가 발생하고, 해당 프로세스는 종료된다.
Kernel Virtual Memory
커널 가상 메모리는 전역이다. 어떤 프로세스가 실행 중이든 상관없이, 항상 같은 방식으로 매핑된다. 핀토스에서 커널 가상 메모리는 물리 메모리와 일대일로 매핑된다. 가상 주소 KERN_BASE는 물리 주소 0로, 가상 주소 KERN_BASE + 0x1234는 물리 주소 0x1234로 매핑된다.
커널 스레드는 커널 가상 메모리 공간과 실행 중인 유저 프로그램의 유저 가상 메모리 공간에 접근할 수 있다. 그러나 커널조차도 실행 중이 아닌 유저 가상 메모리 공간에 접근하려고 하면 page fault 에러가 발생한다.
Memory Layout in Pint OS
+----------------------------------+
| 커널 영역 |
KERN_BASE +----------------------------------+ 0x8004000000
| ? |
USER_STACK +----------------------------------+ 0x47480000
| user stack |
| | |
| | |
| V |
| grows downward |
| |
| |
| |
| |
| grows upward |
| ^ |
| | |
| | |
+----------------------------------+
| uninitialized data segment (BSS) |
+----------------------------------+
| initialized data segment |
+----------------------------------+
| code segment |
+----------------------------------+ 0x400000
| |
| |
| |
| |
| |
0 +----------------------------------+
Accessing User Memory
커널은 유저 프로그램에게서 받은 포인터를 통해서만 유저 메모리에 접근할 수 있다. 유저 프로그램에게서 받은 포인터 널 포인터는 아닌지, 매핑되지 않은 가상 메모리인지, 커널 가상 주소 공간을 가리키는 포인터인지를 확인해야 한다. 포인터들이 이러한 유효하지 않을 경우, 커널이나 다른 실행 중인 프로세스에 손상을 끼치지 않은 채 거부되어야 한다. 문제가 되는 프로세스를 종료하고 그 자원을 풀어줌으로써!
포인터를 검증하는 2가지 방법이 존재한다. 첫 번째 방법은 유저 프로그램에게서 받은 포인터의 유효성을 검증하고, 이를 역참조하는 것이다. thread/mmu.c와 include/threads/vaddr.h의 함수를 참조하자. 이것은 user memory access를 다루는 가장 간단한 방법이다.
두 번째 방법은 유저 포인터가 KERN_BASE 아래를 가리키는지를 확인하고 이를 역참조하는 것이다. 이 방법은 일반적으로 빠르기 때문에 실제 커널에서도 사용되기도 한다.
2가지 중 어떤 방법을 쓰더라도, 누수(leak)되는 자원이 없도록 해야한다. 유저 프로그램이 lock을 쥐고 있거나 동적으로 할당된 메모리를 가지고 있을 때 유효하지 않은 포인터를 만났다면, lock을 풀어주고 할당된 메모리 페이지를 풀어줘야 한다. 첫 번째 방법의 경우 이렇게 하는 것이 간단한 반면, 두 번째 방법의 경우 page fault가 발생하면 에러 코드를 반환받을 방법이 없기 때문에 이를 처리하기가 더 어렵다.
'프로젝트 > Pint OS' 카테고리의 다른 글
[Pint OS] System Calls (2) (0) | 2023.06.11 |
---|---|
[Pint OS] 에러: missing "begin" message (0) | 2023.06.09 |
[Pint OS] System Calls (1) (0) | 2023.06.07 |
[Pint OS] 에러: Kernel panic... thread_yield() (0) | 2023.06.05 |
[Pint OS] Argument Passing (0) | 2023.06.05 |