이 섹션에서는 메모리 매핑 페이지를 구현합니다. 익명 페이지와 달리, 메모리 매핑 페이지는 파일 기반 매핑입니다. 페이지의 내용은 기존 파일의 데이터를 반영합니다. 페이지 폴트가 발생하면 즉시 물리 프레임이 할당되고, 파일로부터 내용이 메모리로 복사됩니다. 메모리 매핑 페이지가 언매핑되거나 스왑 아웃될 때, 내용의 변경 사항은 파일에 반영됩니다.
mmap and munmap System Call메모리 매핑 파일을 위한 두 가지 시스템 콜인 mmap과 munmap을 구현합니다. VM 시스템은 mmap 영역에서 페이지를 지연 로딩(lazily)해야 하며, mmap된 파일 자체를 매핑의 백업 저장소로 사용해야 합니다. 이 두 시스템 콜을 구현하기 위해 vm/file.c에 정의된 do_mmap과 do_munmap을 구현하고 사용해야 합니다.
void *mmap (void *addr, size_t length, int writable, int fd, off_t offset);
*fd로 열린 파일의offset바이트부터 시작하여length바이트를 프로세스의 가상 주소 공간에서addr에 매핑합니다. 전체 파일은addr부터 시작하는 연속된 가상 페이지에 매핑됩니다. 파일 길이가PGSIZE의 배수가 아니면, 마지막 매핑된 페이지의 일부 바이트가 파일 끝을 넘어 "튀어나오게" 됩니다. 페이지가 폴트될 때 이러한 바이트들을 0으로 설정하고, 페이지가 디스크에 다시 쓰일 때는 이들을 버립니다. 성공하면 이 함수는 파일이 매핑된 가상 주소를 반환합니다. 실패하면 파일을 매핑하기에 유효하지 않은 주소인 NULL을 반환해야 합니다.*
fd로 열린 파일의 길이가 0바이트인 경우 mmap 호출은 실패할 수 있습니다. addr이 페이지 정렬되지 않았거나, 매핑된 페이지 범위가 스택이나 실행 파일 로드 시점에 매핑된 페이지를 포함한 기존 매핑된 페이지 집합과 겹치는 경우 반드시 실패해야 합니다. Linux에서는 addr이 NULL이면 커널이 매핑을 생성할 적절한 주소를 찾습니다. 단순화를 위해, 주어진 addr에서 mmap을 시도하면 됩니다. 따라서 addr이 0이면 반드시 실패해야 합니다. 왜냐하면 일부 Pintos 코드는 가상 페이지 0이 매핑되지 않았다고 가정하기 때문입니다. mmap은 length가 0일 때도 실패해야 합니다. 마지막으로, 콘솔 입력과 출력을 나타내는 파일 디스크립터는 매핑 가능하지 않습니다.
메모리 매핑 페이지도 익명 페이지처럼 지연 방식으로 할당되어야 합니다. 페이지 객체를 만들기 위해 vm_alloc_page_with_initializer 또는 vm_alloc_page를 사용할 수 있습니다.
void munmap (void *addr);
지정된 주소 범위
addr에 대한 매핑을 언매핑합니다.addr은 동일한 프로세스의 이전 mmap 호출에 의해 반환되었으며 아직 언매핑되지 않은 가상 주소여야 합니다.
프로세스가 종료될 때, exit를 통하든 다른 방법을 통하든, 모든 매핑은 암묵적으로 언매핑됩니다. 암묵적이든 명시적이든 매핑이 언매핑될 때, 프로세스에 의해 쓰여진 모든 페이지는 파일에 다시 쓰여지고, 쓰여지지 않은 페이지는 쓰여지지 않아야 합니다. 그런 다음 페이지들은 프로세스의 가상 페이지 목록에서 제거됩니다.
파일을 닫거나 제거해도 해당 파일의 어떤 매핑도 언매핑되지 않습니다. 일단 생성되면, Unix 관례를 따라 매핑은 munmap이 호출되거나 프로세스가 종료될 때까지 유효합니다. 자세한 내용은 "열린 파일 제거(Removing an Open File)"를 참조하세요. 각 매핑에 대해 파일에 대한 별도의 독립적인 참조를 얻기 위해 file_reopen 함수를 사용해야 합니다.
두 개 이상의 프로세스가 동일한 파일을 매핑하는 경우, 일관된 데이터를 보아야 한다는 요구사항은 없습니다. Unix는 두 매핑이 동일한 물리 페이지를 공유하도록 하여 이를 처리하며, mmap 시스템 콜에는 클라이언트가 페이지를 공유할지 또는 개인용(즉, copy-on-write)으로 할지 지정할 수 있는 인자도 있습니다.
필요에 따라 vm/vm.c의 vm_file_init과 vm_file_initializer를 수정할 수 있습니다.
void vm_file_init (void);
파일 기반 페이지 하위 시스템을 초기화합니다. 이 함수에서 파일 기반 페이지와 관련된 모든 것을 설정할 수 있습니다.
bool file_backed_initializer (struct page *page, enum vm_type type, void *kva);
파일 기반 페이지를 초기화합니다. 이 함수는 먼저
page->operations에서 파일 기반 페이지에 대한 핸들러를 설정합니다. 메모리를 백업하는 파일과 같은 페이지 구조체의 일부 정보를 업데이트할 수 있습니다.
static void file_backed_destroy (struct page *page);
관련 파일을 닫아 파일 기반 페이지를 파괴합니다. 내용이 더티(dirty)한 경우, 변경 사항을 파일에 다시 쓰도록 해야 합니다. 이 함수에서 페이지 구조체를 해제할 필요는 없습니다.
file_backed_destroy의 호출자가 이를 처리해야 합니다.