在 Linux 上是不是将 boost 内存映射文件归零
Posted
技术标签:
【中文标题】在 Linux 上是不是将 boost 内存映射文件归零【英文标题】:Is boost memory mapped file zeroed on Linux在 Linux 上是否将 boost 内存映射文件归零 【发布时间】:2014-02-25 20:51:46 【问题描述】:我正在重新学习 C++,我需要使用内存映射文件。我决定使用 boost(因为它似乎是可靠的库)。
我创建了一个映射到双精度数组的内存映射文件,并写入该数组中的第一个双精度。磁盘文件在前四个字节中包含一些数据,其余的都归零,这对我来说很奇怪,因为通常如果我在 C++ 中获得指向内存位置的指针,在大多数情况下我必须假设它包含垃圾。
我是否可以保证新创建的内存映射文件将被清零(至少在 Linux 上)?我没有找到任何参考。
BOOST_AUTO_TEST_CASE(OpenMMapFile)
boost::iostreams::mapped_file file;
boost::iostreams::mapped_file_params params;
params.path = "/tmp/mmaptest-1";
params.mode = std::ios::in | std::ios::out;
params.new_file_size = 10*sizeof(double);
file.open(params);
double* data = static_cast<double*>((void*)file.data());
data[0] = 12;
file.close();
这是文件内容:
cat /tmp/mmaptest-1 | base64
AAAAAAAAKEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
编辑
正如@Zan 所指出的 --- boost 实际上使用 ftruncate 来调整 mmaped 文件的大小,因此可以保证归零(至少在 Linux 上)。
【问题讨论】:
在 Unix/Linux 上,操作系统提供了数据不泄露的安全保证,因此当分配文件或内存区域时,它不能允许进程查看磁盘/内存上的内容在以前的文件/进程中。满足此保证的最简单方法是将内存归零。这就是它的作用。 richard 将 linux 与 Windows95 进行比较? 【参考方案1】:内存映射文件包含文件中的任何内容。
如果它是一个新文件,它已被扩展为正确的大小,并且扩展名将包含零。扩展文件通常使用 ftruncate 函数完成。
ftruncate 联机帮助页说:
If the file previously was larger than this size, the extra data is lost. If the file previously was shorter, it is extended, and the extended part reads as null bytes ('\0').
所以是的,零是保证的。
【讨论】:
【参考方案2】:我认为 boost 正在为您将文件归零,以实现映射地址空间真正由磁盘空间而不是稀疏文件备份。 这很慢,特别是如果您想预先创建一个大地址空间, 它可能永远不会被完全使用——只是为了让你可以在这个地址空间中分配许多对象。 他们正在这样做,因为在 UNIX 上没有可用的方法来处理写入内存映射稀疏文件时的磁盘空间不足(暂时忽略 setjmp/longjmp 之类的病态解决方案)。 但是您仍然有可能其他一些进程会截断磁盘上的文件, 在这种情况下,前面提到的问题再次出现。
不幸的是,在存在结构化异常处理的 Windows 上,他们也在这样做(分配与地址空间大小匹配的磁盘空间,而不是使用稀疏文件)。
【讨论】:
这是不真实的,因为正如在这个问题中建立的那样:***.com/q/26682229/7918,实际上磁盘空间没有预先分配! 上次尝试时,对 boost 库的匹配调用挂了很长时间。这可能同时发生了变化,但我对此表示怀疑,因为提到的问题仍然存在。 我刚试过这个,调用 boost 来创建一个托管内存映射文件并在其中分配一个大对象,立即返回。这意味着,在文件创建期间或分配对象时不会分配磁盘空间。这意味着,一个人冒着 SIGSEGV 的风险。请参阅 mmap 的手册页。以上是关于在 Linux 上是不是将 boost 内存映射文件归零的主要内容,如果未能解决你的问题,请参考以下文章