Fil-Backed Page의 경우 디스크에 backed file이 있으므로, swap out될 때 해당 파일에 저장되면 된다.

Swap out되면 해당 페이지의 PTE의 Present Bit은 0이 되고, 해당 페이지에 프로세스가 접근하면 페이지 폴트가 일어나고 디스크의 파일 데이터를 다시 물리 메모리에 올리면서 swap in된다.

file_backed_swap_out() 수정

do_munmap()과 거의 유사하다는 것을 알 수 있다. 단지 do_munmap()은 연속된 가상 메모리 공간에 매핑된 페이지들을 모두 swap out해주는 것이고, file_backed_swap_out()은 한 페이지에 대해 매핑을 해제해준다는 것이 다르다.

static bool file_backed_swap_out (struct page *page) {
	struct file_page *file_page UNUSED = &page->file;

	if (page == NULL)
		return false;
	
	struct container* container = (struct container *)page->uninit.aux;

	/* 수정된 페이지(더티 비트 1)는 파일에 업데이트 해 놓는다. 
		그리고 더티 비트를 0으로 만들어둔다. */
	if (pml4_is_dirty(thread_current()->pml4, page->va)){
		file_write_at(container->file, page->va, 
			container->page_read_bytes, container->offset);
		pml4_set_dirty(thread_current()->pml4, page->va, 0);
	}

	/* present bit을 0으로 만든다. */
	pml4_clear_page(thread_current()->pml4, page->va);
}

file_backed_swap_in() 수정

lazy_load_segment()와 비슷하다는 것을 알 수 있다.

Present Bit이 0으로 세팅되어 있는 File-Backed Page에 프로세스가 접근하게 되면 Supplementary Page Table의 struct page 내에 있는 struct file_page에 접근한다. file_page 구조체의 container 구조체에서 이 가상 페이지와 관련된 디스크의 파일 데이터의 정보를 불러올 수 있다.

이 정보를 토대로 먼저 물리 공간에 프레임을 하나 할당받아 해당 페이지와 매핑해준 다음, 디스크의 파일에서 물리 프레임으로(vm_do_claim_page()swap_in(page, frame->kva)) 데이터를 다시 복사해온다.

static bool file_backed_swap_in (struct page *page, void *kva) {
	struct file_page *file_page UNUSED = &page->file;

	if(page==NULL)
		return false;

	struct container *aux = (struct container *)page->uninit.aux;

	struct file *file = aux->file;
	off_t offset = aux->offset;
	size_t page_read_bytes = aux->page_read_bytes;
	size_t page_zero_bytes = PGSIZE - page_read_bytes;

	file_seek (file, offset);

	if(file_read(file, kva, page_read_bytes) != (int)page_read_bytes) {
		// palloc_free_page(kva);
		return false;
	}

	memset(kva + page_read_bytes, 0, page_zero_bytes);

	return true;		
}