보조 페이지 테이블의 복사
fork가 발생할 시, 보조 페이지 테이블의 복사를 수행해주어야 한다. process.c의 __do_fork()에서 supplemental_page_table_copy()를 호출하면서 보조 페이지 테이블의 복사를 수행한다. 우리는 이 함수를 구현해야 한다.
보조 페이지 테이블을 복사하는 이유는 다음과 같다.
- 프로세스가 fork() 시스템 콜을 통해 자식 프로세스를 생성할 때, 부모 프로세스의 가상 메모리 공간을 자식 프로세스로 복사해야 한다.
- 메모리 보호: 가상 메모리 공간의 복제와 공유를 통해 프로세스 간에 안전한 메모리 보호를 제공할 수 있다. supplemental_page_table_copy() 함수는 필요한 권한과 제약 조건을 유지하면서 보조 페이지 테이블을 복사하여 메모리 보호를 유지할 수 있다.
로직
- 보조 페이지 테이블은 해시 테이블이다.
- 해시 테이블에 담긴 페이지의 타입에 따라 하나하나 복사한다.
- VM_UNINIT인 경우, 페이지가 아직 페이지 폴트가 일어나지 않아서 초기화되지 않은 페이지이므로, 복사해야 할 물리 프레임이 없다. 따라서 가상 주소에 대해서 새로운 page 구조체를 할당하면 된다.
- VM_ANON 또는 VM_FILE인 경우, Lazy loading이 수행되고 초기화된 페이지이므로, 물리 메모리와 매핑되어 있다. 따라서 가상 주소에 대해 새로운 page 구조체를 할당하고 물리 프레임에 대해서도 복사해주면 된다.
supplemental_page_table_copy()
bool
supplemental_page_table_copy (struct supplemental_page_table *dst,
struct supplemental_page_table *src) {
struct hash_iterator i;
hash_first (&i, &src->spt_hash);
while (hash_next (&i)) {
struct page *src_page = hash_entry (hash_cur (&i), struct page, h_elem);
enum vm_type type = VM_TYPE (src_page->operations->type);
void *upage = src_page->va;
bool writable = src_page->writable;
switch (type) {
case VM_UNINIT: {
vm_initializer *init = src_page->uninit.init;
void *aux = src_page->uninit.aux;
vm_alloc_page_with_initializer (VM_ANON, upage, writable, init, aux);
break;
}
case VM_ANON:
case VM_FILE: {
if (!vm_alloc_page (type, upage, writable)) {
return false;
}
if (!vm_claim_page (upage)) {
return false;
}
struct page *dst_page = spt_find_page (dst, upage);
memcpy (dst_page->frame->kva, src_page->frame->kva, PGSIZE);
break;
}
default: {
return false;
}
}
}
return true;
}
make check
supplemental_page_table_copy()을 잘 구현했다면, 약 36개 fail로 줄어들 것이다.
'프로젝트 > Pint OS' 카테고리의 다른 글
[크래프톤 정글 2기] Day 84 (0) | 2023.06.26 |
---|---|
[Pint OS] Stack Growth (0) | 2023.06.25 |
[Pint OS] Lazy loading(2) (0) | 2023.06.19 |
[Pint OS] Lazy loading(1) (0) | 2023.06.18 |
[Pint OS] System Calls (6) (0) | 2023.06.17 |