이 섹션에서는 메모리 매핑 페이지를 구현할 것입니다. 익명 페이지와 달리 메모리 매핑 페이지는 파일 기반 매핑입니다. 페이지의 내용은 기존 파일의 데이터를 미러링합니다. 페이지 폴트가 발생하면 즉시 물리적 프레임이 할당되고 내용이 파일에서 메모리로 복사됩니다. 메모리 매핑 페이지가 매핑 해제되거나 스왑 아웃되면 내용의 변경 사항이 파일에 반영됩니다.

mmapmunmap 시스템 콜

메모리 매핑 파일을 위한 두 가지 시스템 콜인 mmapmunmap을 구현하세요. 여러분의 VM 시스템은 mmap 영역에서 페이지를 지연 로드(lazy load)해야 하며, 매핑을 위한 백업 저장소로 mmaped 파일 자체를 사용해야 합니다. 이 두 가지 시스템 콜을 구현하기 위해 vm/file.c에 정의된 do_mmapdo_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이 매핑되지 않는다고 가정하기 때문입니다. length가 0인 경우에도 mmap이 실패해야 합니다. 마지막으로, 콘솔 입력과 출력을 나타내는 파일 디스크립터는 매핑할 수 없습니다.

메모리 매핑 페이지도 익명 페이지와 마찬가지로 지연 할당(lazy allocation) 방식으로 할당되어야 합니다. 페이지 객체를 만들기 위해 vm_alloc_page_with_initializer 또는 vm_alloc_page를 사용할 수 있습니다.


void munmap (void *addr);

addr로 지정된 주소 범위에 대한 매핑을 해제합니다. 이 주소는 동일한 프로세스에 의해 이전에 호출된 mmap에 의해 반환된 가상 주소여야 하며, 아직 매핑 해제되지 않은 상태여야 합니다.

프로세스가 exit을 통해 또는 다른 방법으로 종료될 때, 모든 매핑은 암시적으로 매핑 해제됩니다. 매핑이 암시적으로 또는 명시적으로 해제될 때, 프로세스에 의해 쓰여진 모든 페이지는 파일에 다시 기록되어야 하며, 쓰여지지 않은 페이지는 기록되지 않아야 합니다. 그런 다음 페이지는 프로세스의 가상 페이지 목록에서 제거됩니다.

파일을 닫거나 제거해도 해당 파일의 매핑은 해제되지 않습니다. 매핑이 생성되면 munmap이 호출되거나 프로세스가 종료될 때까지 유효하며, 이는 Unix 규칙을 따릅니다. 자세한 내용은 열린 파일 제거를 참조하세요. 각 매핑에 대해 파일에 대한 별도의 독립적인 참조를 얻으려면 file_reopen 함수를 사용해야 합니다.

두 개 이상의 프로세스가 동일한 파일을 매핑하는 경우, 일관된 데이터를 볼 것이라는 요구사항은 없습니다. Unix는 두 매핑이 동일한 물리 페이지를 공유하도록 하여 이를 처리하며, mmap 시스템 콜에는 페이지가 공유되는지 또는 개인용인지(즉, 쓰기 시 복사)를 클라이언트가 지정할 수 있는 인수도 있습니다.

vm/vm.c에 있는 vm_file_initvm_file_initializer를 필요에 따라 수정할 수 있습니다.