Categories
Tags
algorithms APIT Arc arm assembly asynchronous base64 BitHacks Blogging box c clang-format client cmake compiler concat concurrency const_fn contravariant cos covariant cpp Customization cybersecurity DataStructure db debugging Demo deserialization discrete doc DP dtruss Dynamic Example FFI flat_map format FP fsanitize Functional functions futures Fuwari GATs gccrs generics gitignore glibc GUI hacking hashmap haskell heap interop invariant iterator join justfile kernel LaTeX leak LFU linux lto MachineLearning macOS Markdown math ML mmap nc OnceLock optimization OS panic parallels perf physics pin postgresql radare2 release reverse RPIT rust sanitizer science Science serialization server shift sin SmallProjects socket std strace String StringView strip strlen surrealdb SWAR swisstable synchronous tan toml traits triangulation UnsafeRust utf16 utf8 Video wsl x86_64 xilem zig
903 words
5 minutes
260308_mmap
link
1. mmap 함수 원형
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);2. 주요 매개변수 및 설정
- addr: 매핑할 주소. 보통
NULL로 설정하여 OS가 결정하게 함. - length: 매핑할 바이트 크기.
- prot (보호 모드):
PROT_READ(읽기),PROT_WRITE(쓰기),PROT_EXEC(실행),PROT_NONE(접근 불가). - flags:
MAP_SHARED(다른 프로세스와 공유, 파일에 반영),MAP_PRIVATE(복사본 생성, 파일에 미반영). - fd:
open()으로 얻은 파일 디스크립터. - offset: 파일 내 매핑 시작 위치 (페이지 크기 단위).
3. mmap 사용 절차
- 파일 열기:
fd = open("file", O_RDWR); - 메모리 매핑:
addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - 파일 조작: 포인터를 사용하여 배열처럼 데이터에 접근.
- 동기화 (선택):
msync(addr, size, MS_SYNC);(메모리 내용을 디스크에 즉시 반영). - 매핑 해제 및 종료:
munmap(addr, size);후close(fd)
4. C 코드 예제
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
int main() {
int fd = open("test.txt", O_RDWR | O_CREAT, 0664);
size_t size = 1024;
ftruncate(fd, size); // 파일 크기 설정 [1]
// 1. mmap으로 파일 매핑
char *map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED)
return -1;
// 2. 포인터로 파일에 쓰기
sprintf(map, "Hello, mmap!");
// 3. 매핑 해제 및 파일 닫기
munmap(map, size);
close(fd);
return 0;
}5. 특징 및 주의사항
- 성능: 대용량 파일 처리 시
read/write시스템 콜 비용을 줄여 성능 향상. - 주의: 매핑 후 파일 크기를 변경하면 예기치 않은 오류 발생 가능.
- 동기화:
MAP_SHARED사용 시에도 실제 파일 반영은 비동기적일 수 있으므로 필요시 msync 호출. - 페이지 단위: 매핑은 페이지 단위(
getpagesize())로 이루어짐. - 메모리 고정: 필요시
mlock()을 통해 페이징 금지 가능
메모리 대응 입출력을 이용한 파일 복사 프로그램 예시
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s <source_file> <dest_file>\n", argv[0]);
exit(1);
}
int srcfd, dstfd; // src 파일 서술자, dst 파일 서술자
void *src, *dst; // src 메모리 주소, dst 메모리 주소
size_t copysz; // 다음 copy할 메모리 내용 size
struct stat sbuf;
off_t fsz = 0; // 다음 읽기, 쓰기를 기록할 위치(offset)
long page_size; // 시스템의 PAGE SIZE
if ((srcfd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr, "can't open %s for reading \n", argv[1]);
exit(1);
}
if ((dstfd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0777)) < 0) {
fprintf(stderr, "can't open %s for writing\n", argv[2]);
exit(1);
}
// file 사이즈 얻기 위한 용도
if (fstat(srcfd, &sbuf) < 0) {
fprintf(stderr, "fstat error\n");
exit(1);
}
if (ftruncate(dstfd, sbuf.st_size) < 0) {
fprintf(stderr, "ftruncate error\n");
exit(1);
}
page_size = sysconf(_SC_PAGESIZE);
printf("page_size : %ld\n", page_size);
while (fsz < sbuf.st_size) {
if ((sbuf.st_size - fsz) > page_size)
copysz = page_size;
else
copysz = sbuf.st_size - fsz;
// src 주소 설정
if ((src = mmap(0, copysz, PROT_READ, MAP_SHARED, srcfd, fsz)) ==
MAP_FAILED) {
fprintf(stderr, "mmap error for input \n");
printf("error : %s\n", strerror(errno));
exit(1);
}
// dst 주소 설정 , 여기서 MAP_SHARED를 MAP_RPIVATE로 바꾸면? dst파일에
// 저장되지 않는다.
if ((dst = mmap(0, copysz, PROT_READ | PROT_WRITE, MAP_SHARED, dstfd,
fsz)) == MAP_FAILED) {
fprintf(stderr, "mmap error for output\n");
exit(1);
}
// src -> dst로 내용 복사
memcpy(dst, src, copysz);
// 메모리 해제
munmap(src, copysz);
munmap(dst, copysz);
// 복사한 내용만큼 다음 메모리 위치를 이동시킬 offset 증가
fsz += copysz;
}
exit(0);
}- result
$ /opt/homebrew/opt/gcc@15/bin/gcc-15 -std=c23 -pedantic -pthread -pedantic-errors -lm -Wall -Wextra -ggdb -Werror -o ./target/a02_mem_io_out ./src/main.c
$ ./target/a02_mem_io_out test.txt
Usage: ./target/a02_mem_io_out <source_file> <dest_file>
$ ./target/a02_mem_io_out test.txt out.txt
page_size : 16384