[완료] mmap에서 공간확보는 되는데 파일 매핑이 되질 않습니다.

binoopang의 이미지

안녕하세요 ^^
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) 

몇 시간째 이유를 찾고 있지만 찾질 못하고 있어 이렇게 감히 질문 글 올립니다.
도움 부탁드립니다 ^^

dobest03의 이미지

제목과 같습니다.

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");

그럼 도움일 되었길..

bushi의 이미지

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 가 강림하십니다.

[bushi@rose net]$ cat mmap.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
 
#define TARGET ((void*)0x09000000UL)
#define MAPSIZ (4096)
 
int main()
{
        int fd;
        const char *file;
 
        printf("PID %d\n", getpid());
 
        fd = open("string", O_RDONLY);
        if (fd < 0) {
                perror("string");
                goto out0;
        }
 
        file = (const char*)mmap(TARGET, MAPSIZ, PROT_READ, MAP_PRIVATE, fd, 0);
        if (file == MAP_FAILED) {
                perror("mmap()");
                goto out1;
        }
 
        if (!memchr(file, 0, MAPSIZ)) {
                fprintf(stderr, "not null-terminated-C-string\n");
                goto out2;
        }
 
        printf("mmaped memory(%p) : %s\n", file, file);
 
 out2:
        munmap((void*)file, MAPSIZ);
 out1:
        close(fd);
 out0:
        return 0;
}
[bushi@rose net]$ 
[bushi@rose net]$ gcc -s -o m mmap.c -Wall
[bushi@rose net]$ 
[bushi@rose net]$ dd if=/var/log/Xorg.0.log of=string bs=4096 count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 4.1649e-05 s, 98.3 MB/s
[bushi@rose net]$
[bushi@rose net]$ dd if=/dev/zero of=string bs=1 count=4080 seek=16
4080+0 records in
4080+0 records out
4080 bytes (4.1 kB) copied, 0.012889 s, 317 kB/s
[bushi@rose net]$ 
[bushi@rose net]$ ./m
PID 19095
mmaped memory(0x9000000) : 
X Window System
[bushi@rose net]$

OTL

binoopang의 이미지

위에 두분 정말 감사합니다.

문제점도 알았고 코딩상의 문제점도 알려주셔서 감사합니다 :D
밥 한번 사고 싶네요 ㅎㅎㅎ

-------- 시그내쳐 ---------
열심히 열심히 열심히 ..
음악을 하는것 처럼!!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.