Project 3 VM 시리즈 1편
PML4만으로 설명되지 않는 lazy page와 VM 메타데이터를 SPT로 분리해서 읽어본다.
Project 3 VM을 시작하면 가장 먼저 부딪히는 질문은 “페이지가 아직 물리 메모리에 없는데도 어떻게 정상 상태로 관리할 수 있나?”이다. 이 글은 그 답으로 등장한 SPT(Supplemental Page Table)를 정리한다.
- PML4와 SPT가 서로 다른 일을 한다는 점을 먼저 분리한다.
- 가상 주소 하나가
struct page로 연결되는 흐름을 본다. - SPT 검색, 삽입, 삭제 코드가 이후 lazy loading, stack growth, swap, mmap의 발판이 되는 이유를 확인한다.
글의 기준은 week11-team-03-pintos-vm의 pair-a 브랜치다. COW는 이번 구현 범위에서 제외한다. 아래 코드는 전체 파일을 통째로 복붙하기 위한 목록이 아니라, diff에서 의미가 바뀐 핵심 블록을 따라 읽기 위한 기준점이다.
1. 왜 PML4만으로는 부족했나
Project 2까지는 “가상 주소가 실제 물리 페이지로 매핑되어 있는가”가 핵심이었다. 하지만 Project 3에서는 아직 메모리에 올라오지 않은 페이지도 정상적으로 존재할 수 있다. 예를 들어 실행 파일의 한 페이지는 지금 당장 읽지 않고, page fault가 난 뒤에 읽을 수 있다.
이전 상태의 한계
PML4는 현재 매핑된 주소만 강하게 설명한다. 아직 frame이 없는 lazy page, swap으로 밀려난 page, mmap으로 파일과 연결된 page의 의도를 담기 어렵다.
변경 후 생긴 기준
SPT는 “이 가상 주소가 어떤 종류의 page인지, 나중에 어떻게 메모리에 올릴지”를 기록한다. 실제 매핑은 PML4가 맡고, VM의 의도와 메타데이터는 SPT가 맡는다.
Page유저 가상 주소 하나를 관리하는 VM 단위다. Pintos에서는 보통 4KB 단위로 생각한다.
Frame실제 물리 메모리 한 칸이다. page가 실행되려면 언젠가 frame을 얻어야 한다.
PML4CPU가 주소 변환에 쓰는 실제 페이지 테이블이다. 현재 매핑 상태를 담당한다.
SPTPintos VM이 page의 종류와 로딩 방법을 기억하는 보조 장부다.
가상 주소0x8048123 같은 유저 주소가 들어온다.
페이지 기준 주소
pg_round_down()으로 4KB 경계에 맞춘다.hash 검색정렬 배열이 아니라 hash table에서 page를 찾는다.
struct pagetype, writable, frame, lazy aux 같은 VM 정보를 들고 있다.
2. SPT가 들고 있는 최소 정보
이 구현에서 SPT의 핵심은 struct page와 struct supplemental_page_table이다. page는 “한 가상 페이지의 설명서”이고, SPT는 그 설명서를 주소 기준으로 찾아주는 hash table이다.
struct page {
const struct page_operations *operations;
void *va;
struct frame *frame;
struct hash_elem hash_elem;
bool writable;
union {
struct uninit_page uninit;
struct anon_page anon;
struct file_page file;
};
};
struct supplemental_page_table {
struct hash spt_hash;
};
va는 page가 대표하는 유저 가상 주소다. 검색 기준이므로 page 단위로 정렬되어 있어야 한다.frame은 현재 물리 메모리에 올라와 있을 때만 연결된다. lazy page라면 처음에는 비어 있을 수 있다.operations는 anon/file/uninit 같은 page 종류별 행동을 고르는 스위치다.hash_elem때문에 page를 SPT hash table 안에 넣을 수 있다.
3. 주소 하나로 page를 찾는 코드
SPT에서 가장 많이 쓰는 함수는 검색이다. page fault가 났을 때도, syscall이 유저 포인터를 검사할 때도, mmap 영역이 이미 있는지 볼 때도 결국 이 함수로 들어온다.
struct page *
spt_find_page (struct supplemental_page_table *spt, void *va) {
struct page p;
struct hash_elem *e;
p.va = pg_round_down (va);
e = hash_find (&spt->spt_hash, &p.hash_elem);
return e != NULL ? hash_entry (e, struct page, hash_elem) : NULL;
}
bool
spt_insert_page (struct supplemental_page_table *spt, struct page *page) {
return hash_insert (&spt->spt_hash, &page->hash_elem) == NULL;
}
void
spt_remove_page (struct supplemental_page_table *spt, struct page *page) {
hash_delete (&spt->spt_hash, &page->hash_elem);
vm_dealloc_page (page);
}
pg_round_down(va)가 빠지면 같은 4KB 페이지 안의 주소들이 서로 다른 page처럼 보일 수 있다.hash_find는 임시 page의 hash_elem을 이용해 같은 va를 가진 실제 page를 찾는다.spt_insert_page가 false라면 이미 같은 가상 페이지가 등록된 상태다. mmap 겹침이나 중복 할당을 잡는 기반이 된다.spt_remove_page는 hash에서만 빼는 함수가 아니라 page 정리까지 이어진다.
4. page를 등록한다는 것은 아직 읽었다는 뜻이 아니다
SPT가 생기면서 중요한 관점이 바뀐다. vm_alloc_page_with_initializer()는 곧바로 물리 메모리를 채우는 함수가 아니다. “이 주소에는 이런 page가 생길 예정”이라고 SPT에 등록하는 함수에 가깝다.
bool
vm_alloc_page_with_initializer (enum vm_type type, void *upage,
bool writable, vm_initializer *init, void *aux) {
struct supplemental_page_table *spt = &thread_current ()->spt;
if (spt_find_page (spt, upage) != NULL)
return false;
struct page *page = malloc (sizeof *page);
if (page == NULL)
return false;
uninit_new (page, pg_round_down (upage), init, type, aux,
type == VM_ANON ? anon_initializer : file_backed_initializer);
page->writable = writable;
return spt_insert_page (spt, page);
}
등록 시점
struct page를 만들고 SPT에 넣는다.아직 없는 것frame과 실제 파일 내용은 없을 수 있다.
나중 시점page fault가 나면 frame을 얻고 데이터를 채운다.
5. 이 단계까지 오면 의미 있는 테스트
이번 글에서 기억할 것
- PML4는 현재 매핑을 설명하고, SPT는 VM이 기억해야 할 page의 의도를 설명한다.
- Project 3에서 page는 frame이 없어도 존재할 수 있다.
- SPT 검색은 page fault, syscall pointer 검증, mmap 겹침 검사에서 계속 다시 쓰인다.
스스로 점검
- 가상 주소 0x8048123을 SPT에서 찾을 때 왜
pg_round_down()이 필요한가? - SPT에 page가 있는데 PML4 매핑은 없을 수 있는 상황을 하나 설명할 수 있는가?
struct page와struct frame을 같은 것으로 보면 어떤 구현이 막히는가?
다음 글 예고
다음 글에서는 SPT에 등록만 해둔 page가 실제 page fault 시점에 어떻게 파일에서 읽히는지 본다.
SPT는 Project 3 VM에서 “아직 메모리에 없지만 존재하는 page”를 설명하기 위한 장부다.