写入 mmap 文件时出现总线错误

got bus error when writing to mmap'ed file

正在尝试使用 mmap 写入文件。不幸的是,循环 map[i] = i; 中的第一个写入将导致总线错误。不知道为什么。

PC运行Ubuntu14.04,文件/tmp/mmapped.bin有12个字节,用./a.out 3调用程序。

谢谢

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

#define FILEPATH "/tmp/mmapped.bin"
//#define NUMINTS  (1000)
#define FILESIZE 0x400000000

int main(int argc, char *argv[])
{
    int i;
    int fd;
    int *map;  /* mmapped array of int's */
    int size = atoi(argv[1]);
    fd = open(FILEPATH, O_RDWR| O_CREAT | O_TRUNC);
    if (fd == -1) {
        perror("Error opening file for reading");
        exit(EXIT_FAILURE);
    }

    map = mmap(0, 4 * size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
        close(fd);
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }

    for (i = 1; i <= size; ++i) {
        map[i] = i;
    }

    if (munmap(map, FILESIZE) == -1) {
        perror("Error un-mmapping the file");
    }
    close(fd);
    return 0;
}

在 c 中,您需要从索引 0 开始。因为它只会将指针递增 i,然后取消引用它。您的代码取消引用超出允许范围的指针。

应该是,

for (i = 0; i < size; ++i) {
    map[i] = i;
}

因为它等同于

for (i = 0; i < size; ++i) {
    *(map + i) = i;
}

另外,使用

map = mmap(0, size * sizeof *map, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

以确保分配足够的 space 并且 *(map + i) 将在范围内。不要使用幻数。

根据 mmap man page,当您 read/write 超出文件范围时,会发生总线错误 (SIGBUS)。

映射的长度与文件的长度是分开的。如果您的文件是新创建的,其大小将为 0,即使您使用 mmap 指定了长度。打开文件后使用 ftruncate 调整文件大小。