Here is the example code I wrote.
#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;
}
If I provide a zero byte foo.txt to this program, it terminates with SIGBUS.
$ > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f8d882ab000
Bus error
If I provide a one byte foo.txt to this program, then there is no such issue.
$ printf A > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f5f3b679000
65
0
0
48
56
10
mmap(2) mentions the following.
Use of a mapped region can result in these signals:
SIGSEGV Attempted write into a region mapped as read-only.
SIGBUS Attempted access to a portion of the buffer that does not correspond to the file (for example, beyond the end of the file, including the case where another process has truncated the file).
So if I understand this correctly, even the second test case (1-byte file) should have led to SIGBUS because data[1]
and data[2]
are trying to access a portion of the buffer (data
) that does not correspond to the file.
Can you help me understand why only a zero byte file causes this program to fail with SIGBUS?
SIGBUS
for both the tests in my question. – Marthmarthaman
page on Linux indicates that any access to a portion of the buffer that does not correspond to the file (for example, beyond the end of the file) should lead to SIGBUS. But my second test seems to contradict what theman
page says on the same Linux system. – Marthmarthammap
clearly states that mappings larger than the underlying file are allowed, but accessing such a page can result inSIGBUS
: Themmap()
function can be used to map a region of memory that is larger than the current size of the object. Memory access within the mapping but beyond the current end of the underlying objects may result inSIGBUS
signals being sent to the process. – Jana