【发布时间】:2017-07-21 18:25:33
【问题描述】:
尝试使用 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;
}
【问题讨论】:
-
open(FILEPATH, O_RDWR| O_CREAT | O_TRUNC);将您的文件截断为零长度。mmap不会为了创建映射而扩展文件;您需要在mmap之前自己扩展文件。此外,零长度映射是有效的,因此您不会遇到映射失败,但生成的映射中没有您有权写入的部分。 -
感谢@twalberg 指出截断。我删除了标志
O_TRUNC(重新编译)并确保文件有12个字节,./a.out 3仍然给出了总线错误。 -
另外,由于您将
map声明为int *,map[3]可能是文件中的 12 个字节(32 位int)或文件中的 24 个字节(64 位)。在任何一种情况下,它都超出了 12 字节文件的结尾...尝试unsigned char *map;... -
有趣的是,它在执行
map[0] = 0时导致崩溃。 -
另一个问题是您尝试
munmap一个比您mmap大得多的区域。当我在mmap之前插入ftruncate调用以确保文件足够大,并修复munmap调用时,我不再遇到失败...