Stack Growth에서 익명 페이지를 다뤘다면, 이제는 한 단계 진화한 파일 기반 가상 메모리다.
바로 mmap()과 munmap()이 그 주인공이다.
메모리에 파일을 맵핑한다(Memory Mapping a File)
즉, 유저 프로그램이 특정 주소에 접근하면, 마치 메모리처럼 동작하지만 실제로는 파일 데이터를 읽는 것이다.
mmap()을 호출하면,→ 이게 바로 Lazy Loading이다.
맵핑을 해제한다(Unmap)
더 이상 파일 데이터를 메모리처럼 접근하지 않도록 한다.
그리고 중요한 게 하나 있다:
mmap() 호출 시:
vm_alloc_page_with_initializer()를 통해 페이지를 등록유저가 해당 주소에 접근하면:
lazy_load_segment()가 호출됨munmap(addr) 호출 시:| 개념 | 설명 |
|---|---|
| Lazy Loading | 실제 접근 시점까지 메모리를 로딩하지 않음 |
| File-backed Page | 파일을 backing store로 사용하는 가상 페이지 |
| Dirty Bit 활용 | 페이지의 수정 여부를 추적해 write-back 수행 |
| Write-back | 메모리 수정 내용을 파일에 되돌려 쓰기 |
| Page Table 활용 | 페이지의 상태와 종류를 kernel이 추적 |
| Resource 관리 | unmap 시점에 자원을 정확히 회수해야 함 |
do_mmap()
├─> for each page:
│ ├─ calculate read/zero bytes
│ ├─ set up load_info
│ └─ vm_alloc_page_with_initializer(VM_FILE, ...)
│
└─> 첫 페이지에 mapped_page_count 저장
→ 유저 접근 → page fault → lazy_load_segment → file_read_at
do_munmap()
├─> for count = mapped_page_count
│ ├─ check dirty bit
│ ├─ if dirty → file_write_at()
│ └─ destroy(page)
| 범주 | 내용 |
|---|---|
| 시스템 콜 구현 | sys_mmap(), sys_munmap() |
| 핵심 로직 함수 | do_mmap(), do_munmap() |
| lazy handler 함수 | lazy_load_segment() |
| file-backed 핸들러 함수들 | file_backed_initializer(), file_backed_swap_in(), file_backed_swap_out(), file_backed_destroy() |
| 파일 정보 보관 구조체 | struct load_info |
| 추적을 위한 필드 | page->mapped_page_count, file_page->file, ofs, read_bytes, zero_bytes 등 |
| dirty 체크 및 write-back | pml4_is_dirty(), file_write_at(), pml4_set_dirty() |
mmap과 munmap은 "파일을 메모리처럼" 다루게 해주는 마법 같은 인터페이스다.
이는 단순한 기능이 아니라 운영체제가 메모리와 저장소를 연결하는 방식을 보여주는 정수이기도 하다.
Stack Growth가 가상 메모리의 시작이었다면,
mmap은 그 확장판이자 실제 운영체제에서 공간 절약과 성능 향상을 동시에 실현하는 중요한 기술이다.
다음 포스팅에서는 구현해야 할 함수들에 대해 더 자세하게 알아보자