Interprocess communication and data sharing under Windows

  

Windows
There are many ways to implement interprocess communication, such as using sockets, pipes, mailslots, and so on. But the most basic and most direct use is memory sharing. Other methods will eventually detour here.

It is conceivable that if there is only one physical memory, this memory can be mapped to the respective virtual address space in different processes, and each process can read the same data. The most efficient method of data exchange. Below we discuss how to implement it.

Shared memory is implemented in Windows using FileMapping. We can create a memory file map object with CreateFileMapping. The CreateFileMapping API will create a kernel object for mapping files to memory. Here, we don't need an actual file, so we don't need to call CreateFile to create a file. The hFile parameter can be filled in with INVALID_HANDLE_VALUE . However, the file length is required to be filled. Windows supports files up to 64bit, but here, our requirements must not exceed 4G, dwMaximumSizeHigh must be 0, and the length can be filled in dwMaximumSizeLow. Then call MapViewOfFile to map to the virtual address of the current process. Once you have used up shared memory, call UnmapViewOfFile to reclaim the memory address space.

Windows has separate the two APIs CreateFileMapping and MapViewOfFile. This is because it allows mapping of files larger than 4G, and the address space is only 4G at maximum (in fact, the average user's program can only use 2G), MapViewOfFile can specify the file's Offset and only map a part.

In the last parameter of CreateFileMapping, pszName fills in a name, then other processes can use this name to call OpenFileMapping to open the FileMapping object and map it in the new process. However, the way to agree on strings seems to be less elegant.

An elegant approach is to use DuplicateHandle to copy a FileMapping object in a new process, and then find a way to notify the new process to the Handle, such as passing the message.

If the two processes that need to share memory are parent-child relationships, then we can notify the FileMapping Handle without message passing. The parent process can directly pass the Handle of the FileMapping to the child process by inheriting the Handle. Of course, you should set properties that can be inherited when you create a CreateFileMapping.

About this:

SECURITY_ATTRIBUTES sa;sa.nLength=sizeof(sa);sa.lpSecurityDescriptor=NULL;sa.bInheritHandle=TRUE;handle=CreateFileMapping(INVALID_HANDLE_VALUE,&sa, PAGE_READWRITE, 0, size, NULL);

Thus, in the case of CreateProcess, if the bInheritHandles parameter is TRUE, all kernel objects with inheritable properties will be copied to the child process.

Note: The inheritance of the kernel object is to create a child process in CreateProcess, but before the main thread of the child process has not been active, the kernel scans all kernel objects in the current process, checks out those with inheritable properties, and then uses DuplicateHandle. Make a copy to the child process. Since it is a kernel object, there is only one copy in the kernel, all of which are just one reference count plus one. The parent and child processes must have the same Handle for the same kernel object.

The process of copying kernel objects is done internally by CreateProcess. We can safely pass the object Handle (same as the child process) to the child process via the command line. Alternatively, it can be passed with environment variables.

It is worth noting that after the child process runs out of this FileMapping object, it needs CloseHandle minus the reference count.

Note: When CreateProcess is called, pszCommandLine cannot directly fill in an unmodifiable string. For example:

CreateProcess("test.exe","test argument",...);

This is wrong because "test argument" will be compiled by the compiler Put it in an unmodifiable data segment. The correct way is:

char cmdline[]="test argument";CreateProcess("test.exe",cmdline,...);

This way, the command line characters The string is placed on the stack and can be read and written.

The second-to-last parameter of CreateProcess needs to fill in a STARTUPINFOW structure. This structure is very complicated and usually takes a lot of trouble to fill. We can copy the structure of a parent process and modify it as appropriate. The method is:

STARTUPINFO si={sizeof(si)};PROCESS_INFORMATION pi;GetStartupInfo(&si);CreateProcess(...,&si,& pi);

Here, the first length information of the STARTUPINFO structure should normally be filled in to ensure the correct execution of GetStartupInfo(&si);

Copyright © Windows knowledge All Rights Reserved