
2025.06.06
오늘한 내용 : PintOS - Project3: Virtual Memory - spt copy, kill 구현
WEEK 13 : 정글 끝까지(PintOS) - Virtual Memory
/* Copy supplemental page table from src to dst */
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, hash_elem);
enum vm_type type = src_page->operations->type;
void *va = src_page->va;
bool writable = src_page->writable;
/* uninit 상태일 때 */
if (type == VM_UNINIT)
{
vm_initializer *init = src_page->uninit.init;
void *aux = src_page->uninit.aux;
/* vm_alloc_page_with_initializer(type, ...) 여기서 type은 최종 타입을 보내줘야함 */
if (!vm_alloc_page_with_initializer(src_page->uninit.type, va, writable,
init, aux))
return false;
}
else
{
/* VM_ANON or VM_FILE 일때 메모리 할당 -> 페이지 요청 -> 메모리 복사 */
if (!vm_alloc_page(type, va, writable))
return false;
/* 물리 프레임 연결 */
if (!vm_claim_page(va))
return false;
/* 실제 물리 프레임 할당을 위해 자식 page 구조체를 찾는다 */
struct page *dst_page = spt_find_page(dst, va);
/* 부모 프레임에서 자식 프레임으로 내용 복사 */
memcpy(dst_page->frame->kva, src_page->frame->kva, PGSIZE);
}
}
return true;
}
/* spt_kill()을 위한 함수 추가*/
void hash_page_destroy(struct hash_elem *e, void *aux)
{
struct page *p = hash_entry(e, struct page, hash_elem);
destroy(p);
free(p);
}
/* Free the resource hold by the supplemental page table */
void supplemental_page_table_kill(struct supplemental_page_table *spt)
{
/* TODO: Destroy all the supplemental_page_table hold by thread and
* TODO: writeback all the modified contents to the storage. */
// 버킷 배열 메모리 자체를 해제
hash_destroy(&spt->spt_hash, hash_page_destroy);
}
process.c
-----------
int process_exec(void *f_name)
{
...
/* We first kill the current context */
process_cleanup();
// 추가 한 부분
#ifdef VM
/* project 3) 새 프로그램 로드를 위해 빈 SPT로 다시 초기화 추가*/
supplemental_page_table_init(&thread_current()->spt);
#endif
...
}
/* check_user_address(const void *uaddr){}
널 포인터 차단 : !uaddr → NULL 이면 즉시 프로세스 종료
유저 영역 검사 : !is_user_vaddr(uaddr) → 주소가 `PHYS_BASE` 이상(커널 영역)에 있으면 종료
매핑 여부 검사 : pml4_get_page(..., uaddr) == NULL => 가상 → 물리 매핑이 안 돼 있으면 종료
*/
void check_user_address(const void *uaddr)
{
#ifndef VM
// project 2
if (!uaddr || !is_user_vaddr(uaddr) || pml4_get_page(thread_current()->pml4, uaddr) == NULL)
{
sys_exit(-1);
}
#else
// project 3
// spt 매핑 여부 검사 : spt_find_page() == NULL -> exit()
if (!uaddr || !is_user_vaddr(uaddr) || spt_find_page(&thread_current()->spt, uaddr) == NULL)
{
sys_exit(-1);
}
#endif
}
잘하고 있는 거겠지? 화이팅!