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

时间:2017-07-21 18:25:33

标签: c linux mmap

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

PC运行Ubuntu 14.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;
}

2 个答案:

答案 0 :(得分:2)

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

确保分配足够的空间并且*(map + i)将在内部边界内。不要使用幻数。

答案 1 :(得分:1)

根据mmap man page,当您在文件范围之外进行读/写时,会发生总线错误(SIGBUS)。

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