시스템프로그래밍_ 9-Memory-mapped file

안수빈·2025년 6월 14일

시스템프로그래밍

목록 보기
4/7
post-thumbnail

<Process Address Space (프로세스 주소 공간)>


**heap과 stack의 확장 방향이 반대로 그려져 있는 거 같음

Text: 프로그램 코드 영역. exec(2) 호출 시 로드됨.
Initialized data: 초기화된 전역 변수들이 들어감. exec(2) 호출 시 로드됨.
Uninitialized data (bss): 초기화되지 않은 전역 변수 영역. exec(2)가 0으로 초기화함.
Heap: 동적 메모리 할당 공간 ex) malloc(). "break" 값을 이용해 늘어남.
Stack: 지역 변수, 함수 호출 스택 프레임, 인자, 반환 주소 등이 저장됨.


Text 영역

  • 프로그램의 CPU 명령어(코드)

  • 읽기 전용 상수도 포함됨

Data 영역

  • 전역 초기화 데이터 + 전역 미초기화 데이터(bss)

  • bss -> Block Started by Symbol의 약자

Heap 영역

  • 동적 메모리 할당 영역 (예: malloc(), new 등)

  • 프로그램 실행 중에 크기가 변할 수 있음

Stack 영역

  • 함수 안의 지역 변수 저장

  • 호출 프레임(매개변수, 반환 주소 등) 저장


<Memory Mapped File>

목적(Objectives)
메모리 영역(ex: struct)을 파일에 매핑하면

  • 런타임 중에 메모리 변수들이 자동으로 파일에 저장됨 ➡︎ Auto-saving

  • 메모리에서 읽는 것은 = 파일에서 읽는 것과 같음

  • 메모리에 쓰는 것은 = 파일에 쓰는 것과 같음 (→ page cache에 기록됨)

  • 파일 데이터를 배열이나 포인터처럼 직접 다룰 수 있음

효과

  • 라이브러리 버퍼와 커널 버퍼 간 복사 과정이 없음
  • 즉, 파일 I/O 성능이 향상

✔️ 여러 프로세스에서 사용하면?

여러 프로세스가 같은 파일을 메모리에 매핑하면,
프로세스 간 통신(IPC) 이 가능해짐 (메모리 영역을 통해 읽고 쓰기)



mmap() 함수 설명

#include <sys/types.h>
#include <sys/mman.h>

caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset);

addr: 매핑할 메모리 영역의 시작 주소
len: 매핑할 크기 (바이트 단위)
prot: 접근 권한 (읽기, 쓰기 등)
flags: 매핑 방식 (공유, 사적 등)
fd: 매핑할 파일의 파일 디스크립터
offset: 파일 내에서 매핑이 시작되는 위치

(반환값)

  • 성공 ➡︎ 매핑된 실제 메모리 영역의 시작 주소
    단, 커널이 addr과 다른 위치에 매핑할 수도 있음

  • 실패 ➡︎ MAP_FAILED


(요약)

  • mmap()을 쓰면 메모리 = 파일처럼 동작

  • 중간 버퍼 생략으로 성능 향상

  • 프로세스 간 공유 메모리 구현도 가능

  • 실패 처리 시 반드시 MAP_FAILED 확인


  • 파일의 일부분을 메모리에 그대로 올려두고 마치 배열처럼 접근할 수 있음

  • 별도로 read()/write() 하지 않아도 파일 I/O 가능!

  • mmap()으로 매핑된 영역은 자동 저장, 빠른 접근, 공유 가능성 등의 장점이 있음!

✔️ mmap()은 파일의 일부를 메모리에 매핑해서 그 파일을 포인터처럼 직접 다루도록 해주는 고성능 I/O 기법이다.


prot – 메모리 접근 권한 설정

PROT_READ: 읽기 허용
PROT_WRITE: 쓰기 허용
PROT_EXEC: 실행 허용
PROT_NONE: 아무 작업도 허용하지 않음

✔️ 해당 영역에 설정된 보호 수준은 파일의 open 모드와 일치해야 함
(ex: 읽기 전용 파일은 PROT_WRITE 못 씀)

flags (매핑 방식) – mmap 동작 방식 설정

MAP_SHARED: 메모리에 쓰는 내용이 파일에도 동기화됨 (공유)
MAP_PRIVATE: 쓰기 동작은 별도의 복사본에만 반영됨 → 원본 파일은 변경되지 않음
MAP_FIXED: 결과 주소가 반드시 인자로 준 주소와 같아야 함. (MAP_FIXED를 지정하지 않으면 주소는 무시되고 커널이 자동 배정)
MAP_NORESERVE: 스왑 공간을 예약하지 않음 (성능 향상을 위한 옵션)

✔️ MAP_SHARED나 MAP_PRIVATE는 반드시 둘 중 하나는 지정해야 함


<메모리 매핑 해제>- munmap()

#include <sys/types.h>
#include <sys/mman.h>

int munmap(caddr_t addr, size_t len);

(매개변수)
addr: 해제할 메모리 영역의 시작 주소
len: 해제할 영역의 크기 (바이트 단위)

(반환값)
0: 성공 시
-1: 실패 시

  • mmap()으로 매핑된 메모리 영역을 명시적으로 해제하려면 munmap()을 호출해야 함
  • addr과 len은 정확히 매핑했던 범위와 일치해야 함

<메모리 매핑 영역을 디스크에 동기화하기>- msync()

#include <sys/mman.h>
#include <unistd.h>

int msync(const void *addr, size_t len, int flags);

(매개변수)
addr : 동기화를 시작할 메모리 주소
len : 동기화할 범위(길이) (바이트 단위)
flags : msync()의 동작 방식을 제어하는 플래그 (예: 동기화 방식 선택)

(반환값)
0: 성공 시
-1: 실패 시

  • mmap()으로 매핑된 메모리 내용이 디스크 파일에 제대로 반영되었는지 확실히 하려면 msync()를 호출해야 해야함
  • MAP_SHARED 매핑일 때만 디스크 동기화가 의미 있음
  • 일반적으로 데이터 손실을 막거나 로그 파일 반영을 보장할 때 사용됨

msync()의 flags 인자 설명

MS_ASYNC (비동기 동기화 요청): 동기화가 완료되기를 기다리지 않음 (즉시 return)

MS_SYNC (동기 동기화 요청): 동기화가 완료될 때까지 블로킹(대기)

MS_INVALIDATE: 동일한 파일에 대해 매핑된 다른 메모리 영역을 무효화함


<Blocking vs Nonblocking I/O>

Blocking I/O

  • I/O 작업이 완료될 때까지 대기함

  • 경우에 따라 영원히 대기할 수도 있음

  • 예시: getchar()키 입력이 있을 때까지 멈춰 있음

Nonblocking I/O

  • 즉시 반환함. I/O가 준비되지 않았으면 에러 반환

예시:

  • 입력 버퍼에 키가 있으면 ➡︎ 키 값을 반환

  • 없으면 ➡︎ 에러와 함께 즉시 반환


<Nonblocking 설정 방법>

open()에서 O_NONBLOCK 플래그 사용

open("a.out", O_RDONLY | O_NONBLOCK);

fcntl()로 플래그 설정하기

  • 플래그 설정 (Nonblocking ON)

  • 플래그 해제 (Nonblocking OFF)

0개의 댓글