메모리매핑 IT CookBook, 유닉스시스템프로그래밍
학습목표 통신프로그램이무엇인지이해한다. 메모리매핑을이용한 IPC 기법을이해한다. 메모리매핑함수를사용해프로그램을작성할수있다. 2/20
목차 메모리매핑의개념 메모리매핑함수 메모리매핑해제함수 메모리매핑의보호모드변경 파일의크기확장 매핑된메모리동기화 데이터교환하기 3/20
메모리매핑의개념 메모리매핑 파일을프로세스의메모리에매핑 프로세스에전달할데이터를저장한파일을직접프로세스의가상주소공간으로매핑 read, write 함수를사용하지않고도프로그램내부에서정의한변수를사용해파일에서데이터를읽거나쓸수있음 메모리매핑과기존방식의비교 기존방식 fd = open( ); lseek(fd, offset, whence); read(fd, buf, len); 메모리매핑함수사용 fd = open( ); addr = mmap((caddr_t)0, len, (PROT_READ PROT_WRITE), MAP_PRIVATE, fd, offset); read 함수를사용하지않고도데이터접근가능 4/20
메모리매핑함수 메모리매핑 : mmap(2) #include <sys/mman.h> void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); fildes 가가리키는파일에서 off 로지정한오프셋부터 len 크기만큼데이터를읽어 addr 이가리키는메모리공간에매핑 prot : 보호모드 PROT_READ : 매핑된파일을읽기만함 PROT_WRITE : 매핑된파일에쓰기허용 PROT_EXEC : 매핑된파일을실행가능 PROT_NONE : 매핑된파일에접근불가 prot 에 PROT_WRITE 를지정하려면 flags 에 MAP_PRIVATE 를지정하고, 파일을쓰기가능상태로열어야함 flags : 매핑된데이터를처리하기위한정보저장 MAP_SHARED : 다른사용자와데이터의변경내용공유 MAP_PRIVATE : 데이터의변경내용공유안함 MAP_FIXED : 매핑할주소를정확히지정 ( 권장안함 ) MAP_NORESERVE : 매핑된데이터를복사해놓기위한스왑영역할당안함 MAP_ANON : 익명의메모리영역주소를리턴 MAP_ALIGN : 메모리정렬지정 MAP_TEXT : 매핑된메모리영역을명령을실행하는영역으로사용 MAP_INITDATA : 초기데이터영역으로사용 5/20
[ 예제 8-1] mmap 함수사용하기 (1) ex8_1.c... 08 int main(int argc, char *argv[]) { 09 int fd; 10 caddr_t addr; 11 struct stat statbuf; 12 13 if (argc!= 2) { 14 fprintf(stderr, "Usage : %s filename\n", argv[0]); 15 exit(1); 16 } 17 18 if (stat(argv[1], &statbuf) == -1) { 19 perror("stat"); 20 exit(1); 21 } 22 23 if ((fd = open(argv[1], O_RDWR)) == -1) { 24 perror("open"); 25 exit(1); 26 } 27 ( 다음쪽 ) 명령행인자로매핑할파일명입력 6/20
[ 예제 8-1] mmap 함수사용하기 (2) ex8_1.c 28 addr = mmap(null, statbuf.st_size, PROT_READ PROT_WRITE, 29 MAP_SHARED, fd, (off_t)0); 30 if (addr == MAP_FAILED) { 31 perror("mmap"); 32 exit(1); 33 } 34 close(fd); 35 36 printf("%s", addr); 37 38 return 0; 39 } 매핑한파일내용출력 # cat mmap.dat HANBIT BOOK # ex8_1.out Usage : ex8_1.out filename # ex8_1.out mmap.dat HANBIT BOOK 파일내용을메모리에매핑 7/20
메모리매핑해제함수 메모리매핑해제 : munmap(2) #include <sys/mman.h> int munmap(void *addr, size_t len); addr 이가리키는영역에 len 크기만큼할당해매핑한메모리해제 해제한메모리에접근하면 SIGSEGV 또는 SIGBUS 시그널발생 [ 예제 8-2] munmap 함수사용하기 ex8_2.c... 08 int main(int argc, char *argv[]) { 09 int fd; 10 caddr_t addr; 11 struct stat statbuf; 12 13 if (argc!= 2) { 14 fprintf(stderr, "Usage : %s filename\n", argv[0]); 15 exit(1); 16 } 17 18 if (stat(argv[1], &statbuf) == -1) { 8/20
[ 예제 8-2] munmap 함수사용하기 (2) ex8_2.c 19 perror("stat"); 20 exit(1); 21 } 22 23 if ((fd = open(argv[1], O_RDWR)) == -1) { 24 perror("open"); 25 exit(1); 26 } 27 28 addr = mmap(null, statbuf.st_size, PROT_READ PROT_WRITE, 29 MAP_SHARED, fd, (off_t)0); 30 if (addr == MAP_FAILED) { 31 perror("mmap"); 32 exit(1); 33 } 34 close(fd); 35 36 printf("%s", addr); 37 38 if (munmap(addr, statbuf.st_size) == -1) { 39 perror("munmap"); 40 exit(1); 41 } 42 43 printf("%s", addr); 44 45 return 0; 46 } 매핑이해제된메모리에접근 # ex8_2.out mmap.dat HANBIT BOOK 파일내용을메모리에매핑 메모리매핑해제 세그멘테이션결함 (Segmentation Fault)( 코어덤프 ) 9/20
메모리매핑의보호모드변경 보호모드변경 : mprotect(2) #include <sys/mman.h> int mprotect(void *addr, size_t len, int prot); mmap 함수로메모리매핑을수행할때초깃값을설정한보호모드를 mprotect 함수로변경가능 prot 에지정한보호모드로변경 10/20
파일의크기확장함수 파일의크기와메모리매핑 존재하지않거나크기가 0 인파일은메모리매핑할수없음 빈파일생성시파일의크기를확장한후메모리매핑을해야함 경로명을사용한파일크기확장 : truncate(3) #include <unistd.h> int truncate(const char *path, off_t length); path에지정한파일의크기를 length로지정한크기로변경 파일기술자를사용한파일크기확장 : ftruncate(3) #include <unistd.h> int ftruncate(int fildes, off_t length); 일반파일과공유메모리에만사용가능 이함수로디렉토리에접근하거나쓰기권한이없는파일에접근하면오류발생 11/20
[ 예제 8-3] ftruncate 함수사용하기 (1) ex8_3.c... 09 int main(void) { 10 int fd, pagesize, length; 11 caddr_t addr; 12 13 pagesize = sysconf(_sc_pagesize); 메모리의페이지크기정보검색 14 length = 1 * pagesize; 15 16 if ((fd = open("m.dat", O_RDWR O_CREAT O_TRUNC, 0666)) == -1) { 17 perror("open"); 18 exit(1); 19 } 20 21 if (ftruncate(fd, (off_t) length) == -1) { 22 perror("ftruncate"); 23 exit(1); 빈파일의크기증가 24 } 25 12/20
[ 예제 8-3] ftruncate 함수사용하기 (2) ex8_3.c 26 addr = mmap(null, length, PROT_READ PROT_WRITE, MAP_SHARED, fd, (off_t)0); 27 if (addr == MAP_FAILED) { 메모리매핑 28 perror("mmap"); 29 exit(1); 30 } 31 32 close(fd); 33 34 strcpy(addr, "Ftruncate Test\n"); 매핑한메모리에데이터쓰기 35 36 return 0; 37 } # ls m.dat m.dat: 해당파일이나디렉토리가없음 # ex8_3.out # cat m.dat ftruncate Test 13/20
매핑된메모리동기화 매핑된메모리동기화 매핑된메모리의내용과백업내용이일치하도록동기화필요 매핑된메모리동기화 : msync(3) #include <sys/mman.h> int msync(void *addr, size_t len, int flags); addr 로시작하는메모리영역에서 len 길이만큼의내용을백업저장장치에기록 flags : 함수의동작지시 MS_ASYNC : 비동기쓰기작업 MS_SYNC : 쓰기작업을완료할때까지 msync 함수는리턴안함 MS_INVALIDATE : 메모리에복사되어있는내용을무효화 14/20
[ 예제 8-4] msync 함수사용하기 (1) ex8_4.c... 08 int main(int argc, char *argv[]) { 09 int fd; 10 caddr_t addr; 11 struct stat statbuf; 12 13 if (argc!= 2) { 14 fprintf(stderr, "Usage : %s filename\n", argv[0]); 15 exit(1); 16 } 17 18 if (stat(argv[1], &statbuf) == -1) { 19 perror("stat"); 파일의상세정보검색 20 exit(1); 21 } 22 23 if ((fd = open(argv[1], O_RDWR)) == -1) { 24 perror("open"); 25 exit(1); 26 } 15/20
[ 예제 8-4] msync 함수사용하기 (2) ex8_4.c 28 addr = mmap(null, statbuf.st_size, PROT_READ PROT_WRITE, 29 MAP_SHARED, fd, (off_t)0); 30 if (addr == MAP_FAILED) { 31 perror("mmap"); 32 exit(1); 33 } 34 close(fd); 35 36 printf("%s", addr); 37 매핑된내용출력 38 printf("---------\n"); 39 addr[0] = 'D'; 40 printf("%s", addr); 매핑된내용수정 41 42 msync(addr, statbuf.st_size, MS_SYNC); 43 44 return 0; 45 } 메모리매핑 수정된내용동기화 # cat mmap.dat HANBIT BOOK # ex8_4.out mmap.dat HANBIT BOOK --------- DANBIT BOOK # cat mmap.dat DANBIT BOOK 16/20
[ 예제 8-5] 데이터교환하기 (1) ex8_5.c 메모리매핑을이용한데이터교환 부모프로세스와자식프로세스가메모리매핑을사용하여데이터교환가능... 09 int main(int argc, char *argv[]) { 10 int fd; 11 pid_t pid; 12 caddr_t addr; 13 struct stat statbuf; 14 15 if (argc!= 2) { 16 fprintf(stderr, "Usage : %s filename\n", argv[0]); 17 exit(1); 18 } 19 20 if (stat(argv[1], &statbuf) == -1) { 21 perror("stat"); 22 exit(1); 23 } 24 17/20
[ 예제 8-5] 데이터교환하기 (2) ex8_5.c 25 if ((fd = open(argv[1], O_RDWR)) == -1) { 26 perror("open"); 27 exit(1); 28 } 29 30 addr = mmap(null, statbuf.st_size, PROT_READ PROT_WRITE, 31 MAP_SHARED, fd, (off_t)0); 32 if (addr == MAP_FAILED) { 33 perror("mmap"); 34 exit(1); 메모리매핑 35 } 36 close(fd); 37 38 switch (pid = fork()) { 39 case -1 : /* fork failed */ fork 함수로자식프로세스생성 40 perror("fork"); 41 exit(1); 42 break; 18/20
[ 예제 8-5] 데이터교환하기 (3) ex8_5.c 43 case 0 : /* child process */ 44 printf("1. Child Process : addr=%s", addr); 45 sleep(1); 46 addr[0] = 'x'; 자식프로세스가매핑된내용수정 47 printf("2. Child Process : addr=%s", addr); 48 sleep(2); 49 printf("3. Child Process : addr=%s", addr); 50 break; 51 default : /* parent process */ 52 printf("1. Parent process : addr=%s", addr); 53 sleep(2); 54 printf("2. Parent process : addr=%s", addr); 55 addr[1] = 'y'; 56 printf("3. Parent process : addr=%s", addr); 57 break; 58 } 59 60 return 0; 61 } 부모프로세스가매핑된내용수정 # cat mmap.dat HANBIT BOOK # ex8_5.out mmap.dat 1. Child Process : addr=hanbit BOOK 1. Parent process : addr=hanbit BOOK 2. Child Process : addr=xanbit BOOK 2. Parent process : addr=xanbit BOOK 3. Parent process : addr=xynbit BOOK 3. Child Process : addr=xynbit BOOK # cat mmap.dat xynbit BOOK # 19/20
IT CookBook, 유닉스시스템프로그래밍