截断内存映射文件
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() 已被弃用。以上是关于截断内存映射文件的主要内容,如果未能解决你的问题,请参考以下文章