【问题标题】:Can I create a file in Windows that only exists in memory - and if so, how?我可以在 Windows 中创建仅存在于内存中的文件吗?如果可以,如何创建?
【发布时间】:2020-05-09 03:16:09
【问题描述】:

这个问题不是这些现有问题的重复:

  • How can I store an object File that only exists in memory as a file inside of my storage system? - 这个问题与 Java 的 File API 无关。
  • Temp file that exists only in RAM? - 这与我的要求很接近,除了 OP 没有询问如何从内存中创建文件以共享将它们传递给子进程李>
  • 我也没有询问 Win32 的内存映射文件 - 因为它们本质上与我所追求的相反:内存映射文件是磁盘上的文件,已映射到进程的虚拟内存空间 - 而我想要的是一个存在于操作系统文件系统(但不是磁盘的物理文件系统)中的文件,如挂载点,并且该文件的数据映射到内存中的现有缓冲区。子>
    • 即,对于内存映射文件,写入/写入特定缓冲区地址和内存偏移量的字节将导致与文件开头相同偏移量的字节被修改 - 但文件物理上存在于磁盘上,这不是我想要的。

详细说明并提供上下文:

  • 我有一个 ASP.NET Core 服务器端应用程序,它定期接收大小在 1 到 10MB 之间的请求流。该程序只能在 Windows / Windows Server 上运行,因此可以使用 Windows 特定的功能。
  • 75% 的时间我的应用程序只是自行读取这些流,仅此而已。
  • 但在少数情况下,它需要让单独的应用程序读取它使用Process.Start 开始的数据并将文件名作为命令行参数传递。

    • 它通过将流保存到磁盘上的临时文件并传递该流的文件名,将数据传递给这些单独的应用程序。
    • 不幸的是,它无法将内容写入子进程的stdin,因为其中一些程序需要磁盘上的文件而不是从stdin 读取。
  • 1234563避免磁盘上的临时文件。
  • 我想避免不必要的缓冲和复制 - 理想情况下,我想将整个 1-10MB 请求流式传输到单个内存缓冲区中,然后将同一缓冲区公开给其他进程 并且使用相同的缓冲区作为临时文件的支持。

  • 如果我在 Linux 上,我可以使用 tmpfs - 它并不完美:

    • 据我所知,现有进程无法指示操作系统获取其虚拟内存的现有区域并将tmpfs 中的文件映射到该内存区域,而tmpfs 仍然需要填充该文件通过将所有数据写入(即复制)其文件描述符 - 这与拥有零拷贝系统的目标背道而驰。
  • Windows 的内置 RAM 磁盘功能仅限于通过第三方设备驱动程序为 RAM 磁盘实现提供基础 - 我很惊讶微软从未在 Windows 中提供内置 RAM 磁盘GUI 或 API,尤其是考虑到它们的相对简单性。

    • The ImDisk program 是使用 Microsoft 的 RAM 磁盘驱动程序平台实现的 RAM 磁盘,但据我所知,虽然它更像 tmpfs,因为它可以创建仅存在于内存中的文件,但它没有t 允许文件数据由正在运行的进程可直接访问的缓冲区(或共享内存缓冲区)支持。

【问题讨论】:

  • 似乎没有用于此目的的用户应用程序级 API。它可以通过实现驱动程序来完成。您能介意分享使用 RAM 的原因吗?为了更好的读/写速度?
  • @RitaHan-MSFT 我想将 1GB 的数据从一个进程传递给一个新的子进程:但该进程只能接受一个文件名,而不是通过 stdin 传递它 - 我会喜欢避免在内存中复制那 1GB。

标签: windows winapi temporary-files memory-mapped-files


【解决方案1】:

CreateFileMappinghFile = INVALID_HANDLE_VALUE创建一个指定大小的文件映射对象,该对象由系统分页文件支持,而不是由文件系统中的文件支持”。

来自 Raymond Chen 的The source of much confusion: “backed by the system paging file”

换句话说,“由系统页面文件支持”只是意味着“像普通虚拟内存一样处理”。

如果内存在被分页之前被释放,那么它永远不会被写入系统分页文件。

【讨论】:

  • 啊,我不知道你可以创建一个页面文件支持的内存映射文件——但是我怎样才能将该文件映射到一个现有的共享内存缓冲区?我看到我可以使用 MapViewOfFileEx 将内存映射文件(包括页面文件支持的映射文件)映射到我的进程的内存空间,但我想我必须使用 MapViewOfFileEx first 并将缓冲区存储到那里 - 但我想知道如果我传入一个指向已分配缓冲区的指针会发生什么。
  • 更新:事实证明你不能。 MapViewOfFileEx 的文档指出:“如果指定的内存区域尚未被调用进程使用,则函数成功”。无赖。
  • @Dai 根据用例,您可以反过来使用映射进行共享,Creating Named Shared MemoryOpenFileMapping
  • 分页文件支持的映射不是程序可以打开的常规文件,因此不满足要求。该程序可以创建一个属性为FILE_ATTRIBUTE_TEMPORARY 的常规文件,以尽可能避免写入磁盘。
  • 如果文件在 ramdisk 上,它可以只存在于内存中。 Dai 提到了这一点,但微软没有随 Windows 分发 ramdisk 驱动程序。如果 Dai 愿意使用 ImDisk 等第三方工具,则可以将 ramdisk 上的文件映射到进程虚拟内存中。
猜你喜欢
  • 1970-01-01
  • 2011-10-31
  • 2019-06-19
  • 1970-01-01
  • 2018-03-14
  • 1970-01-01
  • 2013-11-26
  • 2012-05-02
  • 1970-01-01
相关资源
最近更新 更多