我想使用mmap()
读取具有固定长度(例如64MB)的文件,但是还有一些文件<64MB。
我以长度= 64MB映射此文件(<64MB,例如30MB),当读取超出文件大小(30MB-64MB)的文件数据时,程序得到了bus-error
。
我希望使用固定长度mmap这些文件,并在指针超出文件大小时读取0x00。该怎么做?
我可以想到的一种方法是首先ftruncate
个文件,再将ftruncate
恢复到ori大小,但是我认为这种方法并不完美。
答案 0 :(得分:2)
这是MAP_FIXED
的少数合理用例之一,用于重新映射现有映射的一部分以使用新的后备文件。
这里的一个简单解决方案是无条件mmap
64 MB匿名内存(或显式mmap /dev/zero
),不 MAP_FIXED
并存储结果指针。
接下来,mmap
64 MB或实际文件的实际文件大小(以较小者为准),传递匿名/零mmap
的结果并传递MAP_FIXED
标志。与您的文件相对应的页面将不再是匿名的/零映射的,而将由文件的数据支持;其余页面将由匿名/零页面支持。
完成后,单个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);