mmap(2)

#include <sys/mman.h>
void *mmap(void addr[.length], size_t length, int prot, int flags,
  		   int fd, off_t offset);
int munmap(void addr[.length], size_t length);

Description

mmapfd가 가리키는 파일의 offset 지점을 기준으로 length만큼을 가상 메모리 공간에 매핑해주는 함수이다.

munmap은 매핑한 주소와 length사이만큼의 구간을 unmap 한다. 즉, 해당 구역의 메모리 공간을 비활성화 한다. fd를 닫는다고 unmap이 되지 않는다는 점 유의.

Notes

mmap으로 매핑한 메모리 영역은 fork(2) 를 통해 공유될 수 있다.

wiki

Question

메모리 공간은 랜덤 액세스가 가능하기에 pointer arithmetic또한 가능합니다. mmap을 사용하여 파일과 메모리를 매핑하면 파일(디스크파일, 소켓)도 pointer arithmetic을 사용한 랜덤 액세스가 가능해지나요?

질문의 의도는 Unix IO만을 사용하면 순차읽기밖에 허용하지 않는데, mmap을 사용하면서 랜덤 액세스가 가능해지는 것이 아닌가 궁금했다. 디스크는 랜덤액세스가 가능한 반면, 소켓은 랜덤 액세스가 안되는 거 아닌가?

Answer by @신병철

디스크도 sequential access이다. 다만 그 속도가 (상대적으로) 빨라서 랜덤 액세스 인것처럼 보이는 것이고. lazy demand한 속성으로 인해 메모리 맵 공간은 초기에는 아무것도 메모리에 올라와 있지 않다가 맵 공간 안 임의주소를 참조하면 시작지점부터 해당 주소(가 들어있는 페이지)까지를 읽어들인 뒤에 비로소 그 위치의 값을 참조하게 될 것이다.

stdin과 같이 스트림으로 들어오는 파일은 어떻게 될까? 실험을 해봐야 알겠지만 내 생각엔 해당 메모리 위치가 나올 때까지 Blocking 상태가 될 것 같다.

실험 with mmap & stdin

  1. stdin을 mmap한다. 그 첫 주소의 위치를 stdin_p라고 하자.
  2. *(stdin_p + 10)의 값을 출력한다. 그러면 분명 blocking 상태가 되겠지.
  3. 의도적으로 터미널에 한 글자만(1 byte) 넣고 엔터를 쳐보자.
  4. 긴 문자열 (적어도 10byte는 넘는)을 터미널에 넣고 엔터를 쳐보자.

결과: SEGFAULT

커널 단에서 유저의 입력을 대기할 줄 알았는데, 초기화 되지 않은 맵 영역을 출력하지도 않고 곧장 죽어버린다. 다만 ./a.out < driver.c 와 같이 디스크파일을 프로세스의 stdin으로 리디렉션 하게 만들자 정상적으로 출력이 됐다. 역시 포인터 연산은 아무렇게나 한다고 되는 것이 아니구나. read 따위를 써야겠다.

관련 질문