段错误而使用mmap用C读取二进制文件(Segfault while using mmap in C

2019-09-16 13:42发布

我试图使用mmap用C只是为了看看它到底工作。 目前,我试图通过字节使用mmap读取一个二进制文件的字节。 我的代码是这样的:

#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],我得到一个segfault出现我的问题。 我相信,在二进制文件的第一个字节是一个字符为好。 我的for循环检查是否存在-i标志在编译时,如果有下一个参数应该是文件名。

Answer 1:

看来,因为偏移不是页面大小的倍数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]);


文章来源: Segfault while using mmap in C for reading binary files