【问题标题】:mmap file with larger fixed length with zero padding?具有较大固定长度且填充为零的 mmap 文件?
【发布时间】:2018-08-01 16:54:55
【问题描述】:

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

我mmap这个文件(bus-error。

我希望将这些文件以固定长度映射,并在指针超出文件大小时读取 0x00。该怎么做?

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

【问题讨论】:

  • 您是说您正在读取一个文件,然后将其写入另一个 64MB 的文件吗?或者只是从一个文件中读取,并分配 64MB 给它?如果是后者,那么我认为您从更高级别处理内存错误,您不需要超过文件大小的零(只需有一个大小变量)。
  • @NicholasPipitone hi,其实我是用一组64MB的块来生成纠删码块
  • 您的问题真的与 C 和 C++ 相关吗?仅仅因为 C++ 基于 C 并不会使 C 标记与 C++ 问题相关,反之亦然。

标签: c linux mmap


【解决方案1】:

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

这里一个简单的解决方案是无条件地mmap 64 MB 的匿名内存(或显式地映射/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);

【讨论】:

  • 我不知道你能做到这一点..我不需要它,我只是出于好奇而阅读..但这有点整洁:)。
  • @Rob:我在尝试做更复杂的事情时发现了它;映射几千个文件(都是页面大小的倍数),就好像它们是内存中单个连续的数据块一样。我本可以只使用malloced 并逐个读取每个文件,但我处理的数据量很大,而且读取是随机的,所以花一分钟或更长时间填充缓冲区是一件很痛苦的事;映射等于组合文件大小的单个块,然后使用MAP_FIXED 执行每个文件的重新映射,以在最后一个文件之后立即映射每个文件,在启动时节省超过一分钟的磁盘 I/O。
  • mmaping 在这种情况下的另一个优势是当系统受到内存压力时;如果我 malloced 一个缓冲区并通过 reads 填充它,当系统处于 RAM 压力并且操作系统需要交换时,它必须将 malloced 页面写入交换文件(在一个定义为负载不足且磁盘 I/O 非常宝贵的时间)。使用原始文件的只读共享映射,它可以只删除页面而不写入任何内容,如果需要数据,稍后从磁盘重新加载。
  • 我赞同@Rob 的评论。
  • @ShadowRanger 我以前使用过 mmap 很多次 :) 只是不是将一个文件映射到另一个文件,而且绝对从来没有考虑过使用匿名映射的 /dev/zero 技巧我从来没有尝试过我一直有一个巨大的文件或另一个,所以我从来没有想过:)喜欢它。
猜你喜欢
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
  • 2019-03-16
  • 2013-07-06
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多