구현 목표
• mmap, munmap 시스템 콜을 구현.
• do_mmap, do_munmap 함수(vm/file.c)에 실제 로직 작성.
• 페이지는 lazy load로 할당해야 하며, file-backed로 등록
void *mmap (void *addr, size_t length, int writable, int fd, off_t offset);
• fd 파일의 offset부터 length만큼을 addr 주소에 매핑
• 매핑은 페이지 단위로 이루어지고, lazy allocation
• 성공 시 매핑된 주소 반환, 실패 시 NULL 반환
• addr이 page-aligned가 아님 (pg_round_down() 불가)
• 이미 매핑된 주소 영역과 겹침 (stack, 실행파일 영역 포함)
• addr == 0 → 가상 페이지 0은 Pintos에서 사용하지 않음
• length == 0 → 매핑 의미 없음
• fd가 콘솔 입출력 (0, 1)인 경우 → 매핑 불가
• file_length(fd) == 0 → 매핑할 내용 없음
파일 길이가 4100이면?
• 한 페이지 = 4096바이트이므로 2페이지가 필요
• 두 번째 페이지의 4바이트만 유효하고, 나머지는 “stick out”
• page fault 시: stick out 바이트는 0으로 초기화
• write-back 시: stick out 바이트는 파일에 저장하지 않고 버림
⸻
void munmap (void *addr);
• mmap()으로 매핑된 주소 범위를 해제
• 프로세스가 종료될 때도 모든 매핑이 자동 해제됨 (암시적 unmap)
• dirty 여부와 상관없이 모든 페이지 제거
• 단, dirty 페이지는 파일에 write-back, clean 페이지는 그냥 제거
• SPT(보조 페이지 테이블)에서도 해당 페이지 제거
vm_file_init()
• file-backed 페이지 서브시스템 초기화
file_backed_initializer(struct page *page, ...)
• 페이지의 operations 필드를 file용으로 설정
• backing되는 파일 정보 저장
file_backed_destroy(struct page *page)
• dirty 페이지는 파일에 기록
• 관련 파일 닫기
• page는 이 함수에서 free하지 않음 (호출자가 free)
1. mmap() 호출
2. addr / length / fd 검증
3. file_reopen()으로 독립적인 참조 생성
4. vm_alloc_page_with_initializer() 호출 (type: VM_FILE)
5. page fault 발생 시 → file_read_at()로 파일 내용 로딩
1. munmap() 호출 또는 프로세스 종료
2. 매핑된 영역의 모든 페이지 검사
3. dirty 페이지는 write-back
4. clean 페이지는 바로 제거
5. 보조 페이지 테이블에서 제거
참고 사항
• file_close() 또는 file_remove()로도 mmap된 영역은 사라지지 않음
• unmap은 반드시 munmap()이나 프로세스 종료로 명시적으로 수행해야 함
• file_reopen()을 써서 매핑마다 독립적인 파일 참조를 유지해야 함
전체 흐름
사용자 mmap() 호출
↓
syscall_handler → sys_mmap → do_mmap
↓
SPT에 VM_FILE 타입 페이지 등록 (lazy)
↓
접근 시 page fault 발생
↓
file_backed_initializer → file_backed_claim_page
↓
프레임 할당 + file_read_at()으로 데이터 로딩
↓
사용자 접근 가능
↓
munmap() or exit() 호출 시
↓
dirty면 write-back → 페이지 제거