【发布时间】:2014-02-12 17:50:45
【问题描述】:
将输入文件映射到内存中,然后直接从映射的内存页中解析数据,是一种从文件中读取数据的便捷高效的方式。
但是,除非您可以确保没有其他进程写入映射文件,否则这种做法似乎从根本上也不安全,因为如果底层文件被另一个进程写入,即使私有只读映射中的数据也可能发生变化。 (POSIX 例如doesn't specify“在建立 MAP_PRIVATE 映射后对底层对象所做的修改是否通过 MAP_PRIVATE 映射可见”。)
如果您想在映射文件存在外部更改的情况下确保代码安全,则必须仅通过易失性指针访问映射内存,然后非常小心读取和验证输入的方式,这对于许多用例来说似乎不切实际。
这个分析正确吗?内存映射 API 的文档通常只是顺便提及这个问题,如果有的话,所以我想知道我是否遗漏了什么。
【问题讨论】:
-
在您使用文件时,其他进程可能会修改该文件。内存映射是使用文件的众多方式之一 - 它并不比其他任何方式更不安全。
-
使用普通读取文件 API 将文件内容复制到内存缓冲区中始终是安全的,即使文件被同时修改。相反,如果您通过普通指针访问内存映射文件并且外部进程同时修改它,您会得到未定义的行为,因为这超出了 C(++) 内存模型的约束。通常,如果您或您的编译器期望在您的脚下不断变化的内存,就会发生不好的事情。您在某一时刻验证的输入可能在下一时刻变得无效。
-
您误读了
MAP_PRIVATE的目的。这并不意味着给我一份私人副本,而是意味着我所做的修改对我来说是私人的。它与访问文件的任何其他方法具有所有相同的并发问题 -
@Petesh 我在哪里写或暗示
MAP_PRIVATE的意思是“给我一份私人副本”?我实际上引用了规范中相反的部分。如果有一个选项确实可以确保映射页面一旦被访问就不会被其他进程更改,那就太好了。 -
@StephanTolksdorf 这似乎是你问题的本质。而“确保映射的页面一旦被访问就不会被其他进程更改的选项”是通过写入到页面来完成的。 mmap 只不过是一种方便的读/写
标签: c++ c windows posix memory-mapped-files