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

배재준·2025년 6월 3일

크래프톤 정글 - TIL

목록 보기
78/93
post-thumbnail

2025.06.03

TIL(TODAY I LEARN)


  • 오늘한 내용 : PintOS - Project3: Virtual Memory - frame table 구현!

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


2) frame table 구현

2. 프레임 테이블 & vm_get_frame (vm/vm.c):

페이지를 실제로 RAM에 올릴 수 있도록 프레임 할당 기능 구현.

  • vm_get_frame 구현 - 프레임 생성 및 리스트 연결
 /* palloc() and get frame. If there is no available page, evict the page
  * and return it. This always return valid address. That is, if the user pool
  * memory is full, this function evicts the frame to get the available memory
  * space.*/
 static struct frame *
 vm_get_frame(void)
 {
 	lock_acquire(&frame_table_lock);
 
 	struct frame *frame = NULL;
 	/* TODO: Fill this function. */
 
 	/* 1) 빈 유저 페이지가 있는지 할당 시도 <- 빈 물리 페이지를 할당*/
 	void *kva = palloc_get_page(PAL_USER);
 	if (kva != NULL)
 	{
 		/* 받아온 kva를 관리할 struct frame을 malloc <- 프레임 테이블 위함 */
 		frame = (struct frame *)malloc(sizeof(struct frame));
 		if (frame == NULL)
 		{
 			palloc_free_page(kva);
 			lock_release(&frame_table_lock);
 			return NULL;
 		}
 		frame->kva = kva;
 		frame->page = NULL;
 		list_push_back(&frame_table, &frame->frame_elem); // 프레임 테이블에 넣어줌
 
 		ASSERT(frame != NULL);
 		ASSERT(frame->page == NULL);
 		
 		lock_release(&frame_table_lock);
 		return frame;
 	}
 
 	/* 2) 빈 유저 페이지가 없을 때 evicit(축출) 수행 */
 	struct frame *victim = vm_evict_frame();
 	if (victim == NULL)
 	{
 		/* evicition 실패 했다면 NULL을 리턴
 			함수 상단 주석을 보면 항상 옳은 주소 반환 -> 실패 없음
 		*/
 		lock_release(&frame_table_lock);
 		return NULL;
 	}
 	victim->page = NULL;
 
 	ASSERT(victim != NULL);
 	ASSERT(victim->page == NULL);
 
 	lock_release(&frame_table_lock);
 	return victim;
 }
  • vm_evict_frame() - 물리 페이지 축출 구현
    /* Evict one page and return the corresponding frame.
     * Return NULL on error.*/
    static struct frame *
    vm_evict_frame(void)
    {
    	struct frame *victim = vm_get_victim();
    	/* TODO: swap out the victim and return the evicted frame. */
    	if (victim == NULL)
    		return NULL;
    
    	/* victim이 차지하고 있는 페이지가 있다면 swap_out*/
    	if (!swap_out(victim->page))
    		return NULL;
    
    	return victim;
    }
  • vm_get_victim() : 어떤 방식으로 희생자를 결정할건지
    1. frame을 만들 때 list에 push_back으로 넣었으니 맨 앞의걸 희생자를 선택한다 : FIFO 방식
    2. pml4의 accessed bit를 사용해서 최근 참조된건 1→0 으로 바꾼뒤 맨 뒤로 붙인다(두 번째 기회를 준다) : CLOCK 방식 → 채택!
    
    /* Get the struct frame, that will be evicted. */
    static struct frame *
    vm_get_victim(void)
    {
    	struct frame *victim = NULL;
    	/* TODO: The policy for eviction is up to you. */
    	if (list_empty(&frame_table))
    		return NULL;
    
    	/* FIFO 방식 */
    	// struct list_elem *e = list_pop_front(&frame_table);
    	// victim = list_entry(e, struct frame, frame_elem);
    
    	/* CLOCK 방식 */
    	struct list_elem *e;
    	struct frame *victim;
    	for (e = list_begin(&frame_table); e != list_end(&frame_table);)
    	{
    		victim = list_entry(e, struct frame, frame_elem);
    
    		if (pml4_is_accessed(thread_current()->pml4, victim->page->va))
    		{
    			/* 참조되었으니, second chance: accessed 비트만 0으로 내리고 뒤로 보낸다 */
    			pml4_set_accessed(thread_current()->pml4, victim->page->va, false);
    			e = list_remove(e); // list_next를 반환해줌
    			list_push_back(&frame_table, &victim->frame_elem);
    		}
    		else
    		{
    			/* accessed 비트가 이미 0 → 이게 바로 victim */
    			list_remove(e);
    			return victim;
    		}
    	}
    
    	/* 2) 위 루프에서 victim을 못 찾았다면, 리스트 앞에서 그냥 꺼낸다 (가장 오래된 것) */
    	e = list_pop_front(&frame_table);
    	victim = list_entry(e, struct frame, frame_elem);
    	return victim;
    }
  • vm_claim_page() 구현
    /* Claim the page that allocate on VA. */
    bool vm_claim_page(void *va)
    {
    	struct page *page = NULL;
    	/* TODO: Fill this function */
    	/* 현재 스레드의 spt에서 해당 VA에 할당된 struct page 찾기 */
    
    	page = spt_find_page(&thread_current()->spt, va);
    	if (page == NULL)
    		return false;
    
    	return vm_do_claim_page(page);
    }
    
    /* Claim the PAGE and set up the mmu. */
    static bool
    vm_do_claim_page(struct page *page)
    {
    	struct frame *frame = vm_get_frame();
    
    	/* Set links */
    	frame->page = page;
    	page->frame = frame;
    
    	/* TODO: Insert page table entry to map page's VA to frame's PA. */
    	/* 가상 주소와 물리 주소를 매핑 */
    	pml4_set_page(thread_current->pml4, page->va, frame->kva, page->writable);
    	return swap_in(page, frame->kva);
    	}

0개의 댓글