메모리 매핑 IO — mmap의 동작 원리와 활용
mmap은 파일이나 디바이스를 메모리처럼 접근하게 해주는 시스템 콜입니다. read/write 없이 포인터로 파일을 다룰 수 있어서, 대용량 파일 처리와 프로세스 간 공유 메모리에 널리 사용됩니다.
mmap이란
mmap(memory-mapped I/O) 은 파일이나 디바이스를 프로세스의 가상 주소 공간에 매핑하는 시스템 콜입니다.
일반 파일 I/O:
프로세스 버퍼 ←── read() ←── 커널 버퍼 ←── 디스크
프로세스 버퍼 ──→ write() ──→ 커널 버퍼 ──→ 디스크
mmap I/O:
프로세스 가상 메모리 ←──→ 페이지 캐시 ←──→ 디스크
(포인터로 직접 접근) (자동 동기화)
#include <sys/mman.h>
// 파일을 메모리에 매핑
void *addr = mmap(
NULL, // 커널이 주소 결정
file_size, // 매핑 크기
PROT_READ | PROT_WRITE, // 읽기/쓰기 권한
MAP_SHARED, // 변경사항을 파일에 반영
fd, // 파일 디스크립터
0 // 파일 오프셋
);
// 매핑된 메모리에 직접 접근
char first_byte = ((char*)addr)[0]; // read() 호출 없이!
// 매핑 해제
munmap(addr, file_size);
매핑 유형
파일 매핑 (File-backed Mapping)
파일의 내용을 메모리에 매핑합니다.
MAP_SHARED: 변경 → 파일에 반영 / 다른 프로세스와 공유
MAP_PRIVATE: 변경 → COW로 프로세스 전용 복사본 생성 (파일에 반영 안 됨)
익명 매핑 (Anonymous Mapping)
파일 없이 메모리만 할당합니다.
// 익명 매핑: 파일 없이 메모리 할당
void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
malloc()의 대용량 할당이 내부적으로 mmap을 사용 (glibc에서 보통 128KB 이상)- 공유 익명 매핑(MAP_SHARED | MAP_ANONYMOUS): 부모-자식 프로세스 간 공유 메모리
mmap vs read/write
| 항목 | read/write | mmap |
|---|---|---|
| 데이터 복사 | 커널→유저 버퍼 복사 필요 | 복사 없음 (직접 접근) |
| 시스템 콜 | 매번 필요 | 최초 mmap 한 번 |
| 랜덤 접근 | lseek + read | 포인터 연산 |
| 대용량 파일 | 버퍼 크기만큼 반복 | 전체를 메모리처럼 사용 |
| 캐시 | 커널 + 유저 버퍼 2중 | 페이지 캐시만 (zero-copy) |
활용 사례 사례
데이터베이스
- MongoDB: 과거에 스토리지 엔진이 mmap 기반 (MMAPv1)
- SQLite: WAL 모드에서 mmap 사용 가능
- LMDB: mmap 기반 키-값 저장소
IPC (프로세스 간 통신)
// 공유 메모리 생성 (POSIX)
int fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0666);
ftruncate(fd, SHM_SIZE);
void *ptr = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
// 다른 프로세스에서 같은 공유 메모리 열기
int fd2 = shm_open("/my_shm", O_RDWR, 0666);
void *ptr2 = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0);
실행 파일 로딩
프로그램 실행 시 ELF 바이너리를 mmap으로 메모리에 매핑합니다. 코드 영역은 여러 프로세스가 공유할 수 있습니다.
주의점
- SIGBUS: 파일 크기를 넘는 영역에 접근하면 발생
- msync: MAP_SHARED일 때 변경사항을 디스크에 강제 플러시
- 작은 파일의 순차 읽기에는 read()가 더 나을 수 있음 (mmap 설정 오버헤드)
핵심 포인트
- mmap이 빠른 이유: 커널-유저 버퍼 간 복사가 없음 (zero-copy)
- Demand Paging과 연결: mmap 호출 시 바로 읽지 않고, 실제 접근할 때 페이지 폴트로 로드
- MAP_SHARED vs MAP_PRIVATE: 공유 vs COW — IPC면 SHARED, 읽기 전용이면 PRIVATE
정리
mmap은 파일 I/O를 메모리 접근으로 추상화하여 성능과 편의성을 모두 제공합니다. 데이터베이스, IPC, 실행 파일 로딩 등 시스템 프로그래밍 전반에 활용되며, 실제로는 zero-copy 개념과 페이지 캐시 연결을 설명할 수 있으면 좋습니다.