티스토리 뷰

frame_table

프레임 테이블을 만들어야하는 이유는 뭘까? 우리는 페이지 폴트시 프레임을 할당하고 페이지와 매핑해야한다. 이때 그것을 관리하는 페이지가 필요하게된다. 그렇담 이것을 언제 활용하게 될까?

프레임 테이블은 현재 물리메모리에 올릴수 있는 프레임이 꽉차 더이상 물리메모리에 올릴수 없을때 어느 프레임을 swap out을 할지 정할때 사용하게 된다. 이때 프레임 테이블을 참조해 교체 알고리즘에 때라 swap out할 프레임을 정하게 된다.


struct frame

vm헤더 파일에 frame_table을 정의한다. list로 frame_table을 만든 이유는 clock 교체 알고리즘을 사용하기 위해서다.

그리고 frame 구조체에 프레임 테이블에 삽입할 list_elem을 정의한다.

vm/vm.h

struct list frame_table;

/* The representation of "frame" */
struct frame {
	void *kva;
	struct page *page;

	/* frame table에 접근하기 위해 */
	struct list_elem frame_elem;
};

vm_init

vm_init에서 프레임 테이블을 초기화한다

vm/vm.c

void vm_init(void)
{
	vm_anon_init();
	vm_file_init();
    
	...
    
	/* init frame_table */
	list_init(&frame_table);
}

vm_get_frame

사용자 풀에서 새로운 물리 페이지를 가져오는 함수다. 사용자 풀에서 페이지를 성공적으로 가져오면 프레임도 할당하고 해당 멤버를 초기화한 후 반환한다.vm_get_frame을 구현한 후에는 이 함수를 통해 모든 사용자 공간 페이지(PALLOC_USER)를 할당해야 한다. 아직까지는 물리메모리가 꽉차 프레임을 할당 못하는 경우는 고려하지 않으니 할당을 못하는경우 일단 PANIC("todo")로 표시한다.

/* 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)
{
	/* TODO: Fill this function. */
	struct frame *frame = (struct frame *)malloc(sizeof(struct frame));
	frame->kva = palloc_get_page(PAL_USER);

	/* 할당 가능한 물리 프레임이 없으므로 swap out을 해야 하지만,
		일단 PANIC(todo)로 둔다. */
	if (frame->kva == NULL)
	{
		/* vm_evict_frame 호출 */
		PANIC("todo");
	}

	ASSERT(frame != NULL);

	/* frame table에 생성된 frame을 추가해준다. */
	list_push_front(&frame_table, &frame->frame_elem);
	return frame;
}

vm_do_claim_page

vm_get_frame으로 프레임을 할당 받고 페이지를 매핑하는 작업이다 이때 swap_in이 일어나게 된다.

/* Claim the PAGE and set up the mmu. */
static bool
vm_do_claim_page(struct page *page)
{
	struct frame *frame = vm_get_frame();
	if (frame == NULL)
		return false;

	/* Set links */
	frame->page = page;
	page->frame = frame;
	/* TODO: Insert page table entry to map page's VA to frame's PA. */
	struct thread *t = thread_current();
	void *pml4 = t->pml4;
	/* page - frame이 매핑되어 있지 않다면 */
	if (pml4_get_page(pml4, page->va) == NULL)
	{
		/* 매핑 시켜 주고 */
		if (!pml4_set_page(pml4, page->va, frame->kva, page->writable))
		{
			/* 매핑 되지 않았다면 할당 해제 */
			free(frame);
			return false;
		}
	}
	return swap_in(page, frame->kva);
}

vm_claim_page

가상주소에 해당하는 페이지를 찾고 해당 페이지에 프레임을 할당해 매핑한다.

/* Claim the page that allocate on VA. */
bool vm_claim_page(void *va UNUSED)
{
	struct thread *curr = thread_current();

	va = pg_round_down(va);
	struct page *page = spt_find_page(&curr->spt, va);
	if (page == NULL)
	{
		return false;
	}

	return vm_do_claim_page(page);
}

page fault 발생 했을 때 lazy loading 흐름

1. vm_claim_page(va)

  • va에 해당하는 페이지(page)를 가져온다.
  • vm_do_claim_page(page)를 호출한다.

2. vm_do_claim_page(page)

  • vm_get_frame을 호출하여 새로운 프레임(frame)을 가져온다.
  • page에 frame을 매핑한다.

3. vm_get_frame

  • user_pool로부터 새로운 물리 페이지를 palloc_get_page를 통해 생성한다.

참고

https://casys-kaist.github.io/pintos-kaist/project3/introduction.html
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함