简体   繁体   English

使用Win32 / WINAPI通过内存映射文件传输数据

[英]Transferring data through a memory-mapped file using Win32/WINAPI

I need to transfer some data - char buffer[100000]; 我需要传输一些数据 - char buffer[100000]; - to a child process which is started by me. - 由我开始的儿童过程。

Right now I'm using an ordinary file to do so, the parent process writes the data to a file on disk, and the child process reads it from disk and deletes the file. 现在我使用普通文件来执行此操作,父进程将数据写入磁盘上的文件,子进程从磁盘读取它并删除该文件。 However, that causes unnecessary writes to the disk, so I want to use memory-mapped files instead. 但是,这会导致不必要的磁盘写入,因此我想使用内存映射文件。

How do I create, write to, and then read from a memory-mapped file in such a way that no data is written to disk, except when the pagefile or swap file is used? 除了使用页面文件或交换文件之外,如何以不将数据写入磁盘的方式创建,写入和读取内存映射文件?

Edit: I forgot to specify that I want to use raw WINAPI functions, so the code doesn't have dependencies. 编辑:我忘了指定我想使用原始WINAPI函数,因此代码没有依赖项。 I am researching on how to do it and will post an answer myself when ready, but if someone has ready-made code, they're welcome to save me some effort :) 我正在研究如何做到这一点,并会在准备好后自己发布答案,但如果有人有现成的代码,我们欢迎他们省下一些努力:)

Pass INVALID_HANDLE_VALUE as the file handle when calling CreateFileMapping : 调用CreateFileMapping时,将INVALID_HANDLE_VALUE作为文件句柄传递:

If hFile is INVALID_HANDLE_VALUE, the calling process must also specify a size for the file mapping object in the dwMaximumSizeHigh and dwMaximumSizeLow parameters. 如果hFile为INVALID_HANDLE_VALUE,则调用进程还必须在dwMaximumSizeHigh和dwMaximumSizeLow参数中指定文件映射对象的大小。 In this scenario, CreateFileMapping creates a file mapping object of a specified size that is backed by the system paging file instead of by a file in the file system. 在此方案中,CreateFileMapping创建指定大小的文件映射对象,该对象由系统页面文件而不是文件系统中的文件支持。

You can use either an anonymous file mapping object (pass inheritable handle to child process), or use a named file mapping. 您可以使用匿名文件映射对象(将可继承句柄传递给子进程),也可以使用命名文件映射。

You can use an anonymous file mapping (David Heffernan's answer goes into more detail on this step) with handle inheritance / handle duplication. 您可以使用句柄继承/句柄复制来使用匿名文件映射(David Heffernan的答案在此步骤中详细介绍)。 For example, pass the HANDLE from the parent process on the command-line, then in the child use DuplicateHandle to get a valid HANDLE in the child. 例如,在命令行上从父进程传递HANDLE,然后在子进程中使用DuplicateHandle在子进程中获取有效的HANDLE。

The CreateFileMapping documentation says that CreateFileMapping文档说明了这一点

Multiple processes can share a view of the same file by either using a single shared file mapping object or creating separate file mapping objects backed by the same file. 多个进程可以通过使用单个共享文件映射对象或创建由同一文件支持的单独文件映射对象来共享同一文件的视图。 A single file mapping object can be shared by multiple processes through inheriting the handle at process creation, duplicating the handle, or opening the file mapping object by name. 单个文件映射对象可以由多个进程共享,方法是在创建进程时继承句柄,复制句柄或按名称打开文件映射对象。 For more information, see the CreateProcess, DuplicateHandle and OpenFileMapping functions. 有关更多信息,请参阅CreateProcess,DuplicateHandle和OpenFileMapping函数。

But it may be easier just to use a ramdisk. 但是使用ramdisk可能更容易。

I just found an excellent MSDN article on how to do it, complete with sample code, which I've pasted below. 我刚刚发现了一篇关于如何操作的优秀MSDN文章 ,并附有示例代码,我在下面粘贴了它。

First process (sends the data): 第一个进程(发送数据):

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process.");

int _tmain()
{
   HANDLE hMapFile;
   LPCTSTR pBuf;

   hMapFile = CreateFileMapping(
                 INVALID_HANDLE_VALUE,    // use paging file
                 NULL,                    // default security
                 PAGE_READWRITE,          // read/write access
                 0,                       // maximum object size (high-order DWORD)
                 BUF_SIZE,                // maximum object size (low-order DWORD)
                 szName);                 // name of mapping object

   if (hMapFile == NULL)
   {
      _tprintf(TEXT("Could not create file mapping object (%d).\n"),
             GetLastError());
      return 1;
   }
   pBuf = (LPTSTR) MapViewOfFile(hMapFile,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,
                        0,
                        BUF_SIZE);

   if (pBuf == NULL)
   {
      _tprintf(TEXT("Could not map view of file (%d).\n"),
             GetLastError());

       CloseHandle(hMapFile);

      return 1;
   }


   CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
    _getch();

   UnmapViewOfFile(pBuf);

   CloseHandle(hMapFile);

   return 0;
}

Second process (receives the data): 第二个过程(接收数据):

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")

#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");

int _tmain()
{
   HANDLE hMapFile;
   LPCTSTR pBuf;

   hMapFile = OpenFileMapping(
                   FILE_MAP_ALL_ACCESS,   // read/write access
                   FALSE,                 // do not inherit the name
                   szName);               // name of mapping object

   if (hMapFile == NULL)
   {
      _tprintf(TEXT("Could not open file mapping object (%d).\n"),
             GetLastError());
      return 1;
   }

   pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
               FILE_MAP_ALL_ACCESS,  // read/write permission
               0,
               0,
               BUF_SIZE);

   if (pBuf == NULL)
   {
      _tprintf(TEXT("Could not map view of file (%d).\n"),
             GetLastError());

      CloseHandle(hMapFile);

      return 1;
   }

   MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);

   UnmapViewOfFile(pBuf);

   CloseHandle(hMapFile);

   return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM