pintos 실제 가상 메모리 구조
가상 메모리는 페이지 단위로 나뉘고, 페이지 테이블을 통해 가상 주소를 물리 주소로 매핑한다.
가상 메모리는 물리 메모리 크기와 상관 없이 더 큰 주소 공간을 제공하고, 실제로 필요한 시점에만 물리 메모리를 할당하는 방식이다.
👇pintos에서 가상 메모리와 물리 메모리의 실체
`init.c`에서 Pintos main program을 시작하는 `int main(void)` 함수에서 `paging_init( mem_end )` 함수를 사용하여 페이징 초기화를 해준다. `paging_init( mem_end )` 함수를 보면 pintos 실제 물리 주소 [ 0 ~ mem_end] 범위를 가상 주소에 매핑 해주는 반복문이 나온다.
실제 가상 메모리에서의 KERN_BASE 위의 20MB(pintos의 실제 메모리 용량이라 가정했을 때)를 kva(kernel virtual address space)라 불리며 사용한다. kva는 커널에서 사용하는 가상 주소로 위에 그림과 같이 PA(Physical Address)와 1:1 매핑 된다. 1대1 대응되기 때문에 PA = kva - (KERN_BASE)를 하면 실제 PA 주소를 알 수 있다.
Userstack 밑에 부분은 user space(유저 영역)으로 프로세스에서 사용하는 일반적인 가상 주소 va(virtual address)를 사용한다. 사용자 영역(user space)에서 사용되는 주소로, 각 프로세스마다 별도의 가상 주소 공간을 가지고 있다. 프로세스마다 서로 다른 가상 주소가 같은 물리 주소에 매핑될 수 있다. 가상 메모리 시스템을 통해, 제한된 물리 메모리로 더 많은 메모리 공간을 제공하고 프로세스 간 메모리 보호를 가능하게 한다.
구분 | KVA (Kernel Virtual Address) | VA (Virtual Address) |
사용 주체 | 커널 | 사용자 프로세스 |
매핑 방식 | 물리 주소와 1:1 매핑 | 페이지 테이블을 통한 매핑 |
보호 메커니즘 | 커널만 접근 가능 | 프로세스마다 별도 관리 |
사용 범위 | 커널 내부 | 사용자 프로세스, 커널 호출 시에도 사용 |
👇 paging_init 물리 주소를 가상 주소로 매핑
static void paging_init( uint64_t mem_end ) {
...
for ( uint64_t pa = 0; pa < mem_end; pa += PGSIZE ) {
uint64_t va = (uint64_t)ptov( pa ); // 물리 주소를 가상 주소로 변환
...
👇 kva 내에서는 user pool과 kernel pool 로 정확히 반으로 나뉘어져 관린된다.