메모리 매핑된 파일
이 섹션에서는 메모리 매핑된 페이지를 구현합니다. 익명 페이지와 달리 메모리 매핑된 페이지는 파일을 기반으로 하는 매핑입니다. 페이지 내용은 기존 파일의 데이터를 반영합니다. 페이지 부재가 발생하면 물리적인 프레임이 즉시 할당되고 내용이 파일로부터 메모리로 복사됩니다. 메모리 매핑된 페이지가 매핑 해제되거나 스왑 아웃되면 내용의 변경 사항이 파일에 반영됩니다.
mmap 및 munmap 시스템 콜
메모리 매핑된 파일을 위한 두 가지 시스템 콜인 mmap과 munmap을 구현하세요. VM 시스템은 mmap 영역에서 페이지를 게으르게 로드하고 mmap된 파일 자체를 매핑의 백업 저장소로 사용해야 합니다. 이 두 시스템 콜을 구현하기 위해 **vm/file.c**에 정의된 do_mmap 및 do_munmap 함수를 구현하고 사용해야 합니다.
void *mmap (void *addr, size_t length, int writable, int fd, off_t offset);
길이가 `length` 바이트인 파일을 `fd`로 열어 `offset` 바이트부터 프로세스의 가상 주소 공간인 `addr`에 매핑합니다. 파일 전체가 `addr`에서 시작하는 연속적인 가상 페이지에 매핑됩니다. 파일의 길이가 PGSIZE의 배수가 아닌 경우 최종 매핑된 페이지에서 파일 끝을 넘어가는 몇 바이트가 발생합니다. 이러한 바이트는 페이지 부재 시에 0으로 설정되며, 페이지가 디스크에 기록될 때 폐기됩니다. 성공하면 이 함수는 파일이 매핑된 가상 주소를 반환합니다. 실패한 경우 유효한 파일을 매핑할 수 없는 NULL을 반환해야 합니다.
`mmap` 호출은 파일로 열린 `fd`의 길이가 0바이트인 경우 실패할 수 있습니다. 또한, 만약 `addr`이 페이지 경계에 맞지 않거나, 매핑된 페이지의 범위가 기존에 매핑된 페이지 집합(스택이나 실행 가능한 시간에 매핑된 페이지 포함)과 겹칠 경우에도 실패해야 합니다. Linux에서는 만약 `addr`이 NULL이면 커널이 매핑을 생성할 적절한 주소를 찾습니다. 간단하게 주어진 `addr`에서 `mmap`을 시도할 수 있습니다. 따라서 `addr`이 0인 경우에는 실패해야 합니다. 왜냐하면 Pintos 코드 중 일부에서 가상 페이지 0이 매핑되지 않았다고 가정하기 때문입니다. 또한, `length`가 0인 경우에도 `mmap`은 실패해야 합니다. 마지막으로, 콘솔 입력 및 출력을 나타내는 파일 디스크립터는 매핑할 수 없습니다.
메모리 매핑된 페이지는 익명 페이지와 마찬가지로 게으르게 할당되어야 합니다. `vm_alloc_page_with_initializer` 또는 `vm_alloc_page`를 사용하여 페이지 객체를 만들 수 있습니다.
void munmap (void *addr);
주어진 주소 범위 `addr`에 대한 매핑을 해제합니다. 이 주소는 이전에 동일한 프로세스에서 수행한 `mmap` 호출로부터 반환된 가상 주소여야 하며, 아직 해제되지 않은 상태여야 합니다.
모든 매핑은 프로세스가 종료될 때(exit 또는 다른 수단을 통해) 암시적으로 해제됩니다. 매핑이 해제되면, 암시적으로든 명시적으로든, 프로세스에 의해 기록된 모든 페이지는 파일로 기록되며, 기록되지 않은 페이지는 되어서는 안 됩니다. 그런 다음 이러한 페이지는 프로세스의 가상 페이지 목록에서 제거됩니다.
파일을 닫거나 삭제하는 것은 해당 파일의 매핑 중 하나도 해제하지 않습니다. 한 번 생성된 매핑은 munmap이 호출되거나 프로세스가 종료될 때까지 유효합니다. 이는 Unix 규약을 따릅니다. 더 자세한 정보는 "Removing an Open File"을 참조하세요. 각 매핑에 대해 파일의 독립적인 참조를 얻기 위해 file_reopen 함수를 사용해야 합니다.
만약 두 개 이상의 프로세스가 동일한 파일을 매핑하는 경우, 일관된 데이터를 볼 수 있는 보장이 없습니다. Unix는 두 매핑이 동일한 물리 페이지를 공유하도록 만들어 이 문제를 처리하며, mmap 시스템 호출은 페이지가 공유되는지 아니면 개인적인지(즉, 복사 시에만)를 지정할 수 있는 인자를 제공합니다.
필요에 따라 `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);
연관된 파일을 닫아 파일 기반 페이지를 파괴합니다. 내용이 변경되었으면 변경 사항을 파일에 기록해야 합니다. 이 함수에서는 페이지 구조체를 해제할 필요가 없습니다. `file_backed_destroy`의 호출자가 이를 처리해야 합니다.
'운영체제(OS) > with PintOS' 카테고리의 다른 글
(Project3-Virtual Memory) - Copy-on-write (Extra) (0) | 2023.12.26 |
---|---|
(Project3-Virtual Memory) - Swap In/Out (0) | 2023.12.26 |
(Project3-Virtual Memory) - Stack Growth (0) | 2023.12.26 |
(Project3-Virtual Memory) - Anonymous Page (0) | 2023.12.26 |
(Project3-Virtual Memory) - Memory Management (0) | 2023.12.26 |