【问题标题】:Are Windows Memory Mapped File contents always zeroed by default?默认情况下,Windows 内存映射文件内容是否始终归零?
【发布时间】:2011-06-16 22:48:23
【问题描述】:

我根据经验确定,在我的系统上,创建为特定大小的内存映射文件在默认情况下始终完全归零。例如,使用调用

HANDLE hMM = 
    CreateFileMapping (h,
                        NULL,
                        PAGE_READWRITE,
                        0,
                        0x01400000,//20MB
                        NULL);

.. 写入该文件的映射视图总是会导致一个 20MB 的文件完全归零,除非我写入了非零数据。

我想知道是否可以假定文件的未初始化部分为零。一般情况下,这种行为在 Windows 上是否得到保证?

【问题讨论】:

    标签: c++ windows kernel memory-mapped-files


    【解决方案1】:

    CreateFileMapping 文档(备注部分)明确指出

    如果文件被扩展,文件旧端和新端之间的文件内容不保证为零;行为由文件系统定义。

    所以,如果您在磁盘上的文件一开始是空的,它保证会被清零(因为您正在扩展它);我不认为文件系统驱动程序会冒以这种方式泄露潜在敏感信息的风险,但谁知道呢,也许某些文件系统驱动程序会回收已用于您的进程的页面(这不应该是安全风险)。

    另一方面,我不知道根本不提供安全性的文件系统(例如 FAT)是否会如此关心为您提供它们碰巧为文件的新部分分配的集群的内容.

    相反,如果您创建的内存部分不是由磁盘上的文件支持,而是由分页文件支持,则可以保证您获得的内存全部归零:

    操作系统页面文件支持的文件映射对象中页面的初始内容为0(零)。

    这可能是因为在创建仅内存页面文件时,内存管理器可以完全控制正在发生的事情,并从空白页面池中获取页面。

    【讨论】:

      【解决方案2】:

      所有新分配的页面在用户模式可以访问之前都被清零,因为否则敏感信息可能会从内核模式或其他进程中泄露。这适用于 NtAllocateVirtualMemory/VirtualAllocNtCreateSection/CreateFileMapping 之类的东西。

      我想同样的概念可以扩展到文件,因为任何体面的文件系统都不想以这种方式泄露信息。

      编辑:但是,请对最后一段持保留态度- CreateFileMapping 和SetEndOfFile 的文档都声称未定义文件的扩展部分。我会做更多调查。

      编辑 2:好的,Win32 MSDN 文档肯定是错误的ZwSetInformationFile 的文档指出:

      如果您将 FileInformationClass 设置为 FileEndOfFileInformation 和 EndOfFile 成员 FILE_END_OF_FILE_INFORMATION 指定 超出当前的偏移量 文件结束标记,ZwSetInformationFile 扩展文件并填充 用零扩展。

      所以你去。扩展部分保证为零。

      【讨论】:

      • 不过,您应该遵守所使用接口的约定,而不是实现细节;如果CreateFileMapping 文档说(明确!)不能保证,那么不能保证ZwSetInformationFile 一个实现细节,在 Windows 9x 上 ZwSetInformationFile 不存在,也许在 Windows 12 上它甚至不再存在。
      • @Matteo Italia:谎言。 Win32 充满了谎言,自从我改用 Native API 后,我就再也没有信任过 MSDN 上的任何 Win32 文档。作为一名 Windows 内部专家,我来这里是为了讲述真正发生的事情的真相,而不是 Win32 声称的真相。 :D
      • @wj32:实际上,Win32 的设计“充满谎言”是为了让应用程序在 NT、9x、(部分)Win32s 以及微软未来考虑的任何内核上无缝运行,而无需依赖它们关于特定于平台的实现细节。任何表现良好的 Win32 应用程序都应该只依赖 Win32 合同,以确保在未来的 Windows 版本中继续工作。你没看过Raymond Chen的博客吗? :)
      • @wj32: 再说一遍,它们不是谎言,它是一种类似封装的东西:你的目标是 Win32?然后,您依赖 Win32 保证。您的目标是原生 API?然后,您可以依靠 NT 保证。驱动程序是一个完全不同的问题,暗示它们需要在内核架构更改时进行更改(有时完全重写);他们的目标是一个已知比 Win32 更不稳定的 API(我并不是说 NT API 那个不稳定,我是说 Win32 真的 i> 稳定)。
      • @Matteo Italia:你完全正确。我试图证明我的回答是正确的 - 我正在提供关于正在发生的事情的“内部”角度,仅此而已。
      【解决方案3】:

      是的,正如 wj32 所指出的那样。这与 NT 自诞生以来就满足的 c2 要求有关。但是,根据您要执行的操作,您可能应该查看稀疏文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-01
        • 2021-02-24
        • 2010-11-01
        • 2015-06-13
        • 2011-07-10
        • 1970-01-01
        • 2013-02-03
        • 2016-01-07
        相关资源
        最近更新 更多