
2025.06.04
오늘한 내용 : PintOS - Project3: Virtual Memory - Lazy Init & anonymous page 구현 중!
WEEK 12 : 정글 끝까지(PintOS) - Virtual Memory
3. Lazy Init (VM_UNINIT) (
vm/vm.c,vm/uninit.c):예약된 페이지를 페이지 폴트 시점에 초기화할 수 있도록 연결.
- uninit.h에 선언된 uninit_page 구조체 톺아보기
typedef bool vm_initializer(struct page *, void *aux);
/* Uninitlialized page. The type for implementing the
* "Lazy loading". */
struct uninit_page
{
/* Initiate the contets of the page */
vm_initializer *init; /* 페이지 폴트 시 호출할 초기화 콜백 함수 */
enum vm_type type; /* 최종 페이지 타입(예: VM_FILE, VM_ANON 등) */
void *aux; /* init 함수에 넘겨 줄 추가 파라미터 */
/* Initiate the struct page and maps the pa to the va */
bool (*page_initializer)(struct page *, enum vm_type, void *kva);
};
vm_initializerpage_initializer첫 페이지 폴트 때, 자신이 어떤 타입인지(page_initializer) + 구체 콘텐츠 로딩(init)을 연속적으로 수행”하게 되어 Lazy Init이 완성
vm_alloc_page_with_initializer() 구현 /* Create the pending page object with initializer. If you want to create a
* page, do not create it directly and make it through this function or
* `vm_alloc_page`. */
bool vm_alloc_page_with_initializer(enum vm_type type, void *upage, bool writable,
vm_initializer *init, void *aux)
{
ASSERT(VM_TYPE(type) != VM_UNINIT)
struct supplemental_page_table *spt = &thread_current()->spt;
/* va가 페이지 경계로 정렬되어 있는지 확인 */
void *va = pg_round_down(upage);
/* Check wheter the upage is already occupied or not. */
if (spt_find_page(spt, va) == NULL)
{
/* TODO: Create the page, fetch the initialier according to the VM type,
* TODO: and then create "uninit" page struct by calling uninit_new. You
* TODO: should modify the field after calling the uninit_new. */
struct page *page = (struct page *)malloc(sizeof *page);
if (page == NULL)
return false;
/* uninit_page 구조체 내부 함수 포인터를 결정 */
bool (*page_initializer)(struct page *, enum vm_type, void *kva);
switch (VM_TYPE(type))
{
case VM_ANON:
page_initializer = anon_initializer;
break;
case VM_FILE:
page_initializer = file_backed_initializer;
break;
default:
free(page);
return false;
}
uninit_new(page, va, init, type, aux, page_initializer);
page->writable = writable;
/* TODO: Insert the page into the spt. */
if (!spt_insert_page(spt, page))
{
free(page);
return false;
}
return true;
}
err:
return false;
}
static void
uninit_destroy(struct page *page)
{
struct uninit_page *uninit UNUSED = &page->uninit;
/* TODO: Fill this function.
* TODO: If you don't have anything to do, just return. */
/* uninit 단계에서만 갖고 있는 추가 리소스(aux)가 있으면 해제 */
if (uninit->aux != NULL)
{
free(uninit->aux);
uninit->aux = NULL;
}
}
/* Return true on success */
bool vm_try_handle_fault(struct intr_frame *f, void *addr,
bool user, bool write, bool not_present)
{
struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
struct page *page = NULL;
/* TODO: Validate the fault */
/* TODO: Your code goes here */
/* fault된 가상 주소를 페이지 경계로 내림 */
void *fault_page = pg_round_down(addr);
/* spt에 예약된 uninit 페이지가 있으면 물리 메모리로 올리기 */
page = spt_find_page(spt, fault_page);
if (page != NULL)
return vm_do_claim_page(page);
return false;
}