具有较大固定长度且填充为零的 mmap 文件?

mmap file with larger fixed length with zero padding?

我想用mmap()读取固定长度的文件(例如64MB),但也有一些文件<64MB。

我映射长度为 64MB 的文件(<64MB,例如 30MB),当读取超过文件大小(30MB - 64MB)的文件数据时,程序得到 bus-error.

我想mmap这些固定长度的文件,当指针超出文件大小时读取0x00。怎么做?

我能想到的一种方法是先ftruncate归档,然后ftruncate回ori大小,但我认为这个方法并不完美。

这是 MAP_FIXED 的几个合理用例之一,用于重新映射现有映射的一部分以使用新的支持文件。

这里一个简单的解决方案是无条件地 mmap 64 MB 匿名内存(或显式 mmap /dev/zero), 没有 MAP_FIXED 和存储结果指针。

接下来,mmap 64 MB 或实际文件的实际文件大小(以较小者为准),传递 anonymous/zero mmap 的结果并传递 MAP_FIXED 标志。与您的文件对应的页面将不再 anonymous/zero 映射,而是由您的文件数据支持;其余页面将由 anonymous/zero 页支持。

完成后,单个 munmap 调用将立即取消映射所有 64 MB(您不需要分别取消映射真实文件页面和零备份页面)。

极其简单的例子(没有查错,请自行添加):

// Reserve 64 MB of contiguous addresses; anonymous mappings are always zero backed
void *mapping = mmap(NULL, 64 * 1024 * 1024, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

// Open file and check size
struct stat sb;
int fd = open(myfilename, O_RDONLY);
fstat(fd, &sb);
// Use smaller of file size or 64 MB
size_t filemapsize = sb.st_size > 64 * 1024 * 1024 ? 64 * 1024 * 1024 : sb.st_size;
// Remap up to 64 MB of pages, replacing some or all of original anonymous pages
mapping = mmap(mapping, filemapsize, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0);
close(fd);

// ... do stuff with mapping ...
munmap(mapping, 64 * 1024 * 1024);