Categories
Tags
3d algorithms alignment analyze APIT Arc Architecture arm ascii assembly asynchronous base64 BitHacks Blogging box c c23 clang clang-format client clippy cmake compiler Computer concat concurrency const_fn constexpr contravariant cos covariant cpp cpu crate CS Customization cybersecurity DataStructure db debugging Demo deserialization discrete doc DP drawio dtruss Dynamic emulator example Example FFI flamegraph flat_map fold format FP fsanitize Functional FunctionalProgramming functions futures Fuwari game GATs gcc gccrs generics gitignore glibc GUI hacking hashmap haskell heap hyperfine Imperative interop invariant iterator join justfile kernel LaTeX leak LFU linux lto MachineLearning macOS map Markdown math ML mmap mod nc OnceLock optimization OS ownership panic parallels perf physics pin postgresql product profiling pub radare2 rayon release reverse RPIT rust sanitizer Science science serialization server shift sin size SmallProjects socket std strace String StringView strip strlen struct sum super surrealdb SWAR swisstable synchronous tan thread time toml tracing traits triangulation uint32_t UnsafeRust utf16 utf8 Video vulkan 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