c - 在 C 中使用 mmap 读取二进制文件时出现段错误

标签 c binaryfiles mmap

我正在尝试在 C 中使用 mmap 只是为了看看它是如何工作的。目前我正在尝试使用 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];
    // ......

}

当我尝试 notation = data[0] 并得到段错误时,我的问题出现了。我确信二进制文件中的第一个字节也是一个字符。我的 for 循环在编译时检查是否有 -i 标志,如果有,下一个参数应该是文件名。

最佳答案

看起来 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,您应该将偏移量向下舍入到最接近的倍数,并在访问该区域时将余数加到 i 中。当然,从该函数中获取特定平台的页面大小。它可能在您已经声明的 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]);

关于c - 在 C 中使用 mmap 读取二进制文件时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10164364/

相关文章:

c - 稳定的归并排序C

c - 读取空行时程序崩溃 - c

c - 消息队列不会读取枚举类型的消息

c# - 快速随机访问二进制文件,但在需要时也可以顺序访问。如何布局?

android - 如何使用 C 中的 'mmap' 命令分配特定的内存区域? (安卓NDK)

c - mmap() 拥有内存块

c++ - 控制台程序完成后转换到命令提示符?

c - 在返回的消息中搜索\n\n

python - 在 tensorflow 中与许多输入数据文件很好地混合

unix - mmap 超出文件末尾