[완료] mmap에서 공간확보는 되는데 파일 매핑이 되질 않습니다.
글쓴이: binoopang / 작성시간: 화, 2008/12/16 - 8:45오후
안녕하세요 ^^
mmap 프로그래밍을 처음 시도하고 있는데요
mmap을 사용해서 메모리 공간 확보는 잘 되는데 파일 매핑이 되질 않아 질문 글 올립니다.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <syscall.h> #include <unistd.h> #include <fcntl.h> int main() { int fd; int ret; char *file, *temp; char ch; char buffer[16]; struct stat sb; printf("PID %d\n", getpid()); if((fd=open("string", O_RDONLY)) == -1) puts("open error"); if(fstat(fd, &sb) < 0) { perror("fstat error"); exit(1); } if((file = (char *)mmap(0x9000000, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, fd, 0)) == -1) perror("mmap error"); printf("mmaped memory : %s\n", file); sleep(100); close(fd); return 0; }
위 코드가 문제의 코드 입니다. 이 녀석을 실행하면 일단 메모리 공간은 잘 잡힙니다.
[비누~]$ cat /proc/13408/maps 08048000-08049000 r-xp 00000000 08:01 91879 /home/binoopang/3 08049000-0804a000 rw-p 00000000 08:01 91879 /home/binoopang/3 <span>09000000-09001000 rwxp 09000000 00:00 0 </span> b7dde000-b7ddf000 rw-p b7dde000 00:00 0 b7ddf000-b7f28000 r-xp 00000000 08:06 1434606 /lib/tls/i686/cmov/libc-2.7.so b7f28000-b7f29000 r--p 00149000 08:06 1434606 /lib/tls/i686/cmov/libc-2.7.so b7f29000-b7f2b000 rw-p 0014a000 08:06 1434606 /lib/tls/i686/cmov/libc-2.7.so b7f2b000-b7f2e000 rw-p b7f2b000 00:00 0 b7f44000-b7f47000 rw-p b7f44000 00:00 0 b7f47000-b7f48000 r-xp b7f47000 00:00 0 [vdso] b7f48000-b7f62000 r-xp 00000000 08:06 1417322 /lib/ld-2.7.so b7f62000-b7f64000 rw-p 00019000 08:06 1417322 /lib/ld-2.7.so bfdfc000-bfe11000 rw-p bffeb000 00:00 0 [stack] [비누~]$
그러나 확보된 메모리로 파일 매핑이 되질 않고 모두 0x00 값으로 세팅되어 있습니다.
GDB로 메모리를 확인해 보았습니다.
(gdb) x/128x 0x9000000 0x9000000: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000010: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000020: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000030: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000040: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000050: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000060: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000070: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000080: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000090: 0x00000000 0x00000000 0x00000000 0x00000000 0x90000a0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90000b0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90000c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90000d0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90000e0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90000f0: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000100: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000110: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000120: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000130: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000140: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000150: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000160: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000170: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000180: 0x00000000 0x00000000 0x00000000 0x00000000 0x9000190: 0x00000000 0x00000000 0x00000000 0x00000000 0x90001a0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90001b0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90001c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90001d0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90001e0: 0x00000000 0x00000000 0x00000000 0x00000000 0x90001f0: 0x00000000 0x00000000 0x00000000 0x00000000 (gdb)
몇 시간째 이유를 찾고 있지만 찾질 못하고 있어 이렇게 감히 질문 글 올립니다.
도움 부탁드립니다 ^^
Forums:
MAP_PRIVATE을 빼셔야 합니다.
제목과 같습니다.
MAP_PRIVATE을 빼셔야 합니다. man mmap을 보면 다음처럼 설명되어 잇습니다.
MAP_ANONYMOUS
The mapping is not backed by any file; its contents are initial-
ized to zero. The fd and offset arguments are ignored; however,
some implementations require fd to be -1 if MAP_ANONYMOUS (or
MAP_ANON) is specified, and portable applications should ensure
this. The use of MAP_ANONYMOUS in conjunction with MAP_SHARED
is only supported on Linux since kernel 2.4.
"not backed by any file"
그리고, mmap의 start argument값은 0x9000000보다는 NULL로 주시는 것이 좋습니다.
If start is NULL, then the kernel chooses the address at which to cre-
ate the mapping; this is the most portable method of creating a new
mapping. If start is not NULL, then the kernel takes it as a hint
about where to place the mapping; on Linux, the mapping will be created
at the next higher page boundary. The address of the new mapping is
returned as the result of the call.
mmap의 리턴값인 file의 값 비교도 (void *)-1로 해주시는게 좋을 듯 하네요.. 다음처럼요:
if((file = (char *)mmap(0x9000000, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, fd, 0)) == (void *)-1)
perror("mmap error");
그럼 도움일 되었길..
MAP_ANONYMOUS 는 주어진
MAP_ANONYMOUS 는 주어진 fd 를 무시하고 /dev/zero 를 open/close 없이 사용하기 위한 플래그입니다. mmap 된 공간이 0 으로 읽히는 것이 당연합니다.
open(O_RDONLY) 였으니 mmap(PROT_READ) 가 맞습니다.
mmap() 의 반환값은 (void*) 이므로 형변환이 필요없지만,
PROT_READ 였으니 소스 전체에 걸쳐 const char * 로 통일시켜주는 것이 좋겠습니다.
mmap() 에 실패했을 경우의 반환값은 MAP_FAILED 로 정의되어 있습니다.
간단히 if (file == MAP_FAILED) perror("mmap()") 정도로 사용할 수 있습니다.
mmap() 의 첫번째인자는 충분히 주의깊게 사용하셔야 합니다.
잘만 사용하면 상당히 짜릿한 코딩을 할 수 있지만 남발하면 버그는 물론이고 디버깅조차 불가능해지는 상황이 올 수 있습니다.
C 에서 사용하는 string(이란게 사실 없지만 strlen, printf 에서 요구하는 배열이라치죠)은 반드시 null terminated 여야 합니다.
제대로 검사하지 않으면 난데없는 seg.fault 가 강림하십니다.
OTL
감사합니다 ^^
위에 두분 정말 감사합니다.
문제점도 알았고 코딩상의 문제점도 알려주셔서 감사합니다 :D
밥 한번 사고 싶네요 ㅎㅎㅎ
-------- 시그내쳐 ---------
열심히 열심히 열심히 ..
음악을 하는것 처럼!!
댓글 달기