这是我编写的示例代码。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main()
{
int fd;
long pagesize;
char *data;
if ((fd = open("foo.txt", O_RDONLY)) == -1) {
perror("open");
return 1;
}
pagesize = sysconf(_SC_PAGESIZE);
printf("pagesize: %ld\n", pagesize);
data = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
printf("data: %p\n", data);
if (data == (void *) -1) {
perror("mmap");
return 1;
}
printf("%d\n", data[0]);
printf("%d\n", data[1]);
printf("%d\n", data[2]);
printf("%d\n", data[4096]);
printf("%d\n", data[4097]);
printf("%d\n", data[4098]);
return 0;
}
如果我向这个程序提供一个零字节的 foo.txt,它会以 SIGBUS 终止。
$ > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f8d882ab000
Bus error
如果我向这个程序提供一个字节的 foo.txt,那么就不存在这样的问题。
$ printf A > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f5f3b679000
65
0
0
48
56
10
mmap(2)提到以下内容。
使用映射区域可能会产生以下信号:
SIGSEGV 尝试写入映射为只读的区域。
SIGBUS 试图访问与文件不对应的缓冲区部分(例如,超出文件末尾,包括另一个进程截断了文件的情况)。
因此,如果我理解正确,即使是第二个测试用例(1 字节文件)也应该导致 SIGBUS,因为data[1]
并且data[2]
正在尝试访问data
与文件不对应的缓冲区()的一部分。
你能帮我理解为什么只有一个零字节文件会导致这个程序因 SIGBUS 而失败吗?