Fil-Backed Page의 경우 디스크에 backed file이 있으므로, swap out될 때 해당 파일에 저장되면 된다.
Swap out되면 해당 페이지의 PTE의 Present Bit은 0이 되고, 해당 페이지에 프로세스가 접근하면 페이지 폴트가 일어나고 디스크의 파일 데이터를 다시 물리 메모리에 올리면서 swap in된다.
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);
}
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;
}