[TIL/크래프톤 정글] DAY 87

배재준·2025년 6월 5일

크래프톤 정글 - TIL

목록 보기
79/93
post-thumbnail

2025.06.04

TIL(TODAY I LEARN)


  • 오늘한 내용 : PintOS - Project3: Virtual Memory - Lazy Init & anonymous page 구현 중!

  • WEEK 12 : 정글 끝까지(PintOS) - Virtual Memory


3) Lazy Init 구현

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_initializer
    • 자체가 구현된 함수는 아니고, 페이지 타입별로 사용할 콜백 함수들이 저 형태를 따라야 한다는 것을 정의
    • 예약 시점에 넘겨준 구체적인 초기화 로직을 수행한다.
  • page_initializer
    • 페이지가 어느 타입(VM_FILE vs. VM_ANON)인지 보고, 최소한의 물리 메모리 세팅을 한다.

첫 페이지 폴트 때, 자신이 어떤 타입인지(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;
    }
  • uninit_destroy() 구현
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;
	}
}
  • vm_try_handle_fault() 구현
/* 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;
}

0개의 댓글