Wednesday, March 26, 2008

mmap()

파일을 메모리에 올려놓고 사용할 때 쓴느 mmap()은 아래와 같이 생겼다.

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

fd가 물고 있는 파일의 offset 주소부터 len만큼 메모리의 addr에 맵핑하는데, prot/flags 옵션을 준다..라고 생각하면된다. prot는 실행/읽기/쓰기 권한을 지정하는 것이고, flags는 메모리를 프로세스간 공유할 것인지 혹은 '꼭' addr 주소에 mmap 되야함을 알려주는 역할을 한다. mmap을 하게 되면 fd의 reference count가 한개 올라간다. 즉 mmap을 위한 fd가 생긴다. 때문에 mmap할 때 열었던 fd는 닫아도 된다. 새로 생성된 fd는 munmap하거나 프로세스가 종료하면 해제된다. 실제 사용예는 아래와 같다.

void *p;
p = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0);
if (p == MAP_FAILED) perror("mmap");

mmap은 페이지 길이 단위로 할당되기 때문에 주소가 이 align에 맞아야 한다. 길이가 page size의 정수배가 아닌경우 한 페이지 정도의 공간을 더 할당하고 남은 공간에 0을 채워준다(이 공간은 나중에 file에 sync되지 않는다) 페이지 길이를 확인하는 방법은 sysconf(), getpagesize(), PAGE_SIZE가 있는데 두번째 것은 리눅스에서만 지원하고 세번째는 컴파일 타임에 얻어오는 것이라 여러 아키텍쳐에서 돌릴 수 없다. 그러니 sysconf(_SC_PAGESIZE)로 값을 얻어오자. mmap()의 반환 값은 man을 참조하기로 하자. 이 놈은 더이상 유효하지 않은 영역에 접근하거나 읽기전용인 곳에 쓰려고 할때 시그널을 준다.

munmap()은 할당된 mmap을 해제할 때 쓰는데 아래와 같이 간단하다.

if(mmunmap(addr, len) == -1) perror("munmap");

간단히 mmap()의 장점을 요약하면 아래와 같다.

  • avoid extraneous copy (disk -> kernel buffer -> user buffer ...)

  • does not incur system call

  • mmaped data can be shared

  • use pointer instead of lseek()


반대로 mmap()의 단점을 요약하면 아래와 같다.

  • 페이지 단위로 맵핑되므로 작은 파일에 대해서는 공간 낭비가 있다. (4kb for 7 bytes file!)

  • fragmentation of large file in process address space at 32bit architecture

  • creating & maintaining overhead (can be reduced by double copy elimination)

No comments:

Post a Comment