截断内存映射文件

Posted

技术标签:

【中文标题】截断内存映射文件【英文标题】:Truncating memory mapped file 【发布时间】:2011-09-28 18:16:26 【问题描述】:

我想使用读/写内存映射文件来管理我正在创建的一些索引 (unsigned int)。

我已经按照 here 和 here 找到的代码示例进行了操作

我最初不知道文件的大小,因此我计划将其制作为大约 4K 以开始并相应地增长。

但是,我不确定在完成地图后如何截断文件。因此,如果我只在文件中使用大约 1K,我想将其截断为 1K,而不是在此过程中浪费 3K。我关心的不是浪费文件空间,而是我检查文件的大小以确定我有多少unsigned int

编辑

所以要澄清一下...虽然文件是内存映射的...我正在分配 4K 块...当我完成内存映射文件时,我想清理文件,所以它正是我想要的已经投入了。

【问题讨论】:

【参考方案1】:

使用ftruncate 截断文件,它只需要文件描述符和大小。然后稍后您可以使用fstat 查询基础文件的属性,并使用您从那里获得的大小来确定未来映射的维度。

【讨论】:

那是线程安全的吗?如果ftruncate 一个文件而另一个线程正在使用它?【参考方案2】:

如果您 ftruncate() 文件,您必须“同时”将 mremap() 映射到新大小。您可以对范围做类似的事情(但这可能会导致 mremap 将段放置在地址空间的不同部分)

【讨论】:

我认为 mremap() 不是标准函数...所以我只是 munmap() 然后 mmap()...无论如何,ftruncate() 对我有用...跨度> 你是对的。它不在 POSIX 中。 Linux 有,True64/OSF 有。 BSD 似乎有一个具有不同语义的。但是:如果它存在,它可能比 munmap() + mmap() 组合便宜。 这不是必须的。您可以mmap 超过文件的实际大小,并且在文件末尾写入超过一页将导致SIGBUS。如果你在写之前用ftruncate增加大小,你应该没问题。 这只是实现我所谓的“同时”的一种方式。如果您必须处理多个 mmap() 区域,这将变得更加困难:信号处理程序(或由它调用的东西)必须找出哪些区域导致了故障。【参考方案3】:

当您尝试优化时,请使用 getpagesize() 返回的值。那是标准的系统内存页大小,不需要截断。

【讨论】:

我澄清了我的问题......我的目的不是在文件被内存映射时截断......而是在我完成文件之后...... 文件系统类似。检查您系统的文件块大小,我认为它是 4 kB 甚至更多。 对...我知道文件有块大小,但正如我在问题中提到的那样,我检查文件的大小以确定我有多少个无符号整数。顺便说一句,我发现 getpagesize() 已被弃用。

以上是关于截断内存映射文件的主要内容,如果未能解决你的问题,请参考以下文章

内存映射文件

内存映射大文件

高效率场景-内存映射

内存映射文件原理探索

内存映射文件原理探索

linux中匿名内存映射映射到哪个文件?