Memory Mapped I/O (mmap)
Memory Mapped I/O는 파일 디스크립터(fd)를 직접 사용하는 대신, 파일을 메모리에 매핑하여 접근하는 방식이다. 이를 통해 시스템 콜을 최소화하고, 데이터를 빠르게 읽고 쓸 수 있다.

mmap() - 파일을 메모리에 매핑
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
매개변수 설명
- addr : 매핑할 메모리 주소를 커널에게 '제안' (보통 0 입력하여 자동 지정)
- len : 매핑할 크기 (바이트 단위)
- prot : 메모리 보호 설정 (비트 OR 연산 사용 가능)
- PROT_READ : 읽기 가능
- PROT_WRITE : 쓰기 가능
- PROT_EXEC : 실행 가능
- flags : 매핑 속성을 설정
- MAP_PRIVATE : 다른 프로세스와 공유하지 않음 (Copy-on-Write)
- MAP_SHARED : 같은 파일을 매핑한 다른 프로세스와 공유
- MAP_FIXED : 특정 주소에 매핑 강제
- fd : 매핑할 파일의 파일 디스크립터
- offset : 파일에서 매핑을 시작할 위치 (페이지 크기 단위로 정렬 필요, 예: 4KB)
반환값 : 성공 시 매핑된 메모리 주소, 실패 시 MAP_FAILED
munmap() - 메모리 매핑 해제
int munmap(void *addr, size_t len);
- addr : 매핑을 해제할 메모리 주소
- len : 해제할 메모리 크기
- 반환값 : 성공 시 0, 실패 시 -1
Reference Count (참조 카운트)
파일을 메모리에 매핑하면 Reference Count가 증가하며, 파일 디스크립터(fd)를 닫아도 매핑된 메모리는 유지된다.
예제: fd를 닫아도 메모리에서 파일 접근 가능
int main(int argc, char *argv[]){
struct stat sb;
char *p;
int fd;
if(argc < 2){
printf("Usage: %s <pathname>\n", argv[0]);
exit(1);
}
fd = open(argv[1], O_RDONLY);
if(fd == -1){
perror("open");
exit(1);
}
if(fstat(fd, &sb) == -1){
perror("fstat");
exit(1);
}
if(!S_ISREG(sb.st_mode)){
printf("Not a file\n");
exit(1);
}
p = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if(p == MAP_FAILED){
perror("mmap");
exit(1);
}
close(fd); // 파일 디스크립터를 닫아도 매핑된 메모리는 유지됨
for(off_t len = 0; len < sb.st_size; len++){
putchar(p[len]);
}
munmap(p, sb.st_size);
return 0;
}
실행 예시
./a.out file1.txt
konkuk university
Reference Count가 감소하는 경우
- munmap() 호출 시
- 프로세스가 종료될 때
mmap vs Unix IO
장점
- 낮은 오버헤드: read(), write()와 달리 커널과의 컨텍스트 스위칭 없이 메모리에 직접 접근 가능
- 공유하기 쉬움: MAP_SHARED 옵션을 사용하면 여러 프로세스가 동일한 메모리를 공유 가능
- Seek 속도가 빠름: lseek() 없이 메모리 포인터만 조정하면 특정 위치로 이동 가능
단점
- 공간 낭비 : 페이지 크기(예: 4KB) 단위로만 매핑 가능하므로, 6KB 매핑 시 8KB 사용
- 매핑 크기 제한: 프로세스의 가상 메모리 공간 내에서만 매핑 가능
- 매핑 시 큰 오버헤드: 매핑 설정 시 시스템 자원이 소모되며, 작은 파일에 대해 반복적인 매핑은 비효율적
Memory Mapped I/O는 높은 성능과 효율성을 제공하지만, 매핑 크기와 오버헤드 관리에 신경 써야 한다. 적절한 상황에서 mmap()을 활용하면 시스템 성능을 크게 향상시킬 수 있다.
반응형
'CS 지식 > 시스템 프로그래밍' 카테고리의 다른 글
[C언어] 프로세스 Sleep개념과 관련 시스템 콜(System call) (0) | 2025.03.02 |
---|---|
[C언어] 리눅스 Time과 Clock의 종류와 POSIX Clocks (0) | 2025.03.02 |
[C언어] 다중화된 입출력(Multiplexed IO) 관련 시스템 콜(System call) (0) | 2025.03.02 |
[C언어] File I/O (Unix vs Standard IO)관련 시스템 콜(System call) (0) | 2025.03.02 |
[C언어] 리눅스 파일 시스템과 file table의 구조(inode, offset등) (0) | 2025.03.02 |
댓글