2012-04-15 88 views
4

我想在C中使用mmap来查看它是如何工作的。目前我尝试使用mmap逐字节读取二进制文件。我的代码是这样的:在C中使用mmap读取二进制文件时出现Segfault错误

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/mman.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h>  

int main(int argc, char *argv[]) { 
    int fd; 
    char *data; 

    for (int i = 1; i<argc; i++) 
    { 

     if(strcmp(argv[i],"-i")==0) 
      fd = open(argv[i+1],O_RDONLY); 
    } 

    data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000); 
    int i = 0; 
    notation = data [i]; 
    // ...... 

} 

当我尝试记数法=数据[0]和我得到一个段错误时,我的问题发生。我相信二进制文件中的第一个字节也是一个字符。我的for循环检查编译时是否有-i标志,如果有下一个参数应该是文件名。

+0

确定该文件的大小至少为8000字节?另外,手册页中提到“offset必须是由sysconf(_SC_PAGE_SIZE)返回的页面大小的倍数”。作为次要方面,您应该将fd初始化为-1,以防用户未指定-i参数,并且for循环应该循环到argc-1,否则您将访问argv,超出了用户指定的传入参数 - 我作为最后一个参数。 – EricS 2012-04-15 17:39:30

回答

4

看起来mmap失败了,因为偏移量不是页面大小的倍数。你可以用perror来测试它,看看问题是一个无效的参数。如果你写:

data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000); 
perror("Error"); 

至少在我的OS X打印以下错误:

错误:无效的参数

改变从8000偏移到4096级或8192的作品。 6144没有,所以它必须是这个平台上4096的倍数。顺便说一句,

printf("%d\n",getpagesize()); 

4096打印要圆向下偏移,为MMAP的这个最接近的整数倍,其余访问该地区时,添加到我。当然,从该功能获取特定平台的页面大小。它可能在你已经声明的unistd.h中定义。

以下是如何正确处理偏移量并处理可能的错误。它打印位置8000处的字节:

int offset = 8000; 
int pageoffset = offset % getpagesize(); 

data = mmap(NULL, 4000 + pageoffset, PROT_READ, MAP_SHARED, fd, offset - pageoffset); 
if (data == MAP_FAILED) { 
    perror ("mmap"); 
    exit (EXIT_FAILURE); 
} 
i = 0; 
printf("%c\n",data [i + pageoffset]); 
+0

+1斑点:-) – cnicutar 2012-04-15 17:48:35

+0

因此,在完成所有这些之后,我仍然以数据为空。但我的bin文件的大小是16MB。有什么想法吗 ? – AndroidDev93 2012-04-15 18:06:52

+0

你以后在做什么数据?我注意到页面偏移量也必须添加到长度4000.使用当前代码,您应该能够访问字节8000到11999. – jjrv 2012-04-15 18:10:58