interprocess.qbk

来自「Boost provides free peer-reviewed portab」· QBK 代码 · 共 1,625 行 · 第 1/5 页

QBK
1,625
字号
[section:shared_memory_what_is What is shared memory?]Shared memory is the fastest interprocess communication mechanism.The operating system maps a memory segment in the address space of severalprocesses, so that several processes can read and write in that memory segment without calling operating system functions. However, we need some kind of synchronization between processes that read and write shared memory.Consider what happens when a server process wants to send an HTML file to a client processthat resides in the same machine using network mechanisms:* The server must read the file to memory and pass it to the network functions, that  copy that memory to the OS's internal memory.* The client uses the network functions to copy the data from the OS's internal memory  to its own memory.As we can see, there are two copies, one from memory to the network and another onefrom the network to memory. And those copies are made using operating system callsthat normally are expensive. Shared memory avoids this overhead, but we need to synchronize both processes:* The server maps a shared memory in its address space and also gets access to a  synchronization mechanism. The server obtains exclusive access to the memory using  the synchronization mechanism and copies the file to memory.* The client maps the shared memory in its address space. Waits until the server releases  the exclusive access and uses the data.Using shared memory, we can avoid two data copies, but we have to synchronize the accessto the shared memory segment.[endsect][section:shared_memory_steps Creating memory segments that can be shared between processes]To use shared memory, we have to perform 2 basic steps:* Request to the operating system a memory segment that can be shared betweenprocesses. The user can create/destroy/open this memory using a [*shared memory object]:['An object that represents memory that can be mapped concurrently into the   address space of more than one process.].* Associate a part of that memory or the whole memory with the address space of the  calling process. The operating system looks for a big enough memory address range  in the calling process' address space and marks that address range as an  special range. Changes in that address range are automatically seen  by other process that also have mapped the same shared memory object.Once the two steps have been successfully completed, the process can start writing toand reading from the address space to send to and receive data from other processes.Now, let's see how can we do this using [*Boost.Interprocess]:[endsect][section:shared_memory_header Header]To manage shared memory, you just need to include the following header:[c++]   #include <boost/interprocess/shared_memory_object.hpp>[endsect][section:shared_memory_creating_shared_memory_segments Creating shared memory segments]As we've mentioned we have to use the `shared_memory_object` class to create, openand destroy shared memory segments that can be mapped by several processes. We canspecify the access mode of that shared memory object (read only or read-write),just as if it was a file:* Create a shared memory segment. Throws if already created:[c++]      using boost::interprocess;      shared_memory_object shm_obj         (create_only                  //only create         ,"shared_memory"              //name         ,read_write                   //read-write mode         );* To open or create a shared memory segment:[c++]      using boost::interprocess;      shared_memory_object shm_obj         (open_or_create               //open or create         ,"shared_memory"              //name         ,read_only                    //read-only mode         );* To only open a shared memory segment. Throws if does not exist:[c++]      using boost::interprocess;      shared_memory_object shm_obj         (open_only                    //only open         ,"shared_memory"              //name         ,read_write                   //read-write mode         );When a shared memory object is created, its size is 0.To set the size of the shared memory, the user must use the `truncate` functioncall, in a shared memory that has been opened with read-write attributes:[c++]      shm_obj.truncate(10000);As shared memory has kernel or filesystem persistence, the user must explicitlydestroy it. The `remove` operation might fail returningfalse if the shared memory does not exist, the file is open or the file is still memory mapped by other processes:[c++]      using boost::interprocess;      shared_memory_object::remove("shared_memory");For more details regarding `shared_memory_object` see the [classref boost::interprocess::shared_memory_object] class reference.[endsect][section:shared_memory_mapping_shared_memory_segments Mapping Shared Memory Segments]Once created or opened, a process just has to map the shared memory object in the process'address space. The user can map the whole shared memory or just part of it. Themapping process is done using the `mapped_region` class. The class representsa memory region that has been mapped from a shared memory or from other devicesthat have also mapping capabilities (for example, files). A `mapped_region` can becreated from any `memory_mappable` object and as you might imagine, `shared_memory_object`is a `memory_mappable` object:[c++]      using boost::interprocess;      std::size_t ShmSize = ...      //Map the second half of the memory      mapped_region region         ( shm                      //Memory-mappable object         , read_write               //Access mode         , ShmSize/2                //Offset from the beginning of shm         , ShmSize-ShmSize/2        //Length of the region         );            //Get the address of the region      region.get_address();      //Get the size of the region      region.get_size();The user can specify the offset from the mappable object where the mapped regionshould start and the size of the mapped region. If no offset or size is specified,the whole mappable object (in this case, shared memory) is mapped. If the offsetis specified, but not the size, the mapped region covers from the offset untilthe end of the mappable object.For more details regarding `mapped_region` see the [classref boost::interprocess::mapped_region] class reference.[endsect][section:shared_memory_a_simple_example A Simple Example]Let's see a simple example of shared memory use. A server process creates ashared memory object, maps it and initializes all the bytes to a value. After that, a client process opens the shared memory, maps it, and checksthat the data is correctly initialized. This is the server process:[import ../example/doc_shared_memory.cpp][doc_shared_memory]Now the client process:[import ../example/doc_shared_memory2.cpp][doc_shared_memory2][endsect][section:emulation Emulation for systems without shared memory objects][*Boost.Interprocess] provides portable shared memory in terms of POSIXsemantics. Some operating systems don't support shared memory as defined byPOSIX:*  Windows operating systems provide shared memory using memory backed by the   paging file but the lifetime semantics are different from the ones   defined by POSIX (see [link interprocess.sharedmemorybetweenprocesses.sharedmemory.windows_shared_memory   Native windows shared memory] section for more information).*  Some UNIX systems don't support shared memory objects at all. MacOS is   one of these operating systems.In those platforms, shared memory is emulated with mapped files createdin the temporary files directory. Because of this emulation, shared memoryhas filesystem lifetime in those systems.[endsect][section:removing Removing shared memory][classref boost::interprocess::shared_memory_object shared_memory_object]provides a static `remove` function to remove a shared memory objects.This function [*can] fail if the shared memory objects does not exist orit's opened by another process. Note that this function is similar to thestandard C `int remove(const char *path)` function. In UNIX systems, `shared_memory_object::remove` calls `shm_unlink`:*  The function will remove the name of the shared memory objectnamed by the string pointed to by name.*  If one or more references to the shared memory object exist whenis unlinked, the name will be removed before the function returns, but theremoval of the memory object contents will be postponed until all open andmap references to the shared memory object have been removed.*  Even if the object continues to exist after the last function call, reuse ofthe name will subsequently cause the creation of a[classref boost::interprocess::shared_memory_object] instance to behave as if noshared memory object of this name exists (that is, trying to open an objectwith that name will fail and an object of the same name can be created again).In Windows operating systems, the function fails if the object is being used,so a programmer can't consider the UNIX behavior as the portable behavior:`shared_memory_object::remove` [*can] fail if the shared memory is still in use,but this does not mean that it [*will] fail if it's in use. Just the samebehavior as the standard C (stdio.h) `int remove(const char *path)` function.[endsect][section:anonymous_shared_memory Anonymous shared memory for UNIX systems]Creating a shared memory segment and mapping it can be a bit tedious when severalprocesses are involved. When processes are related via `fork()` operating system call in UNIX systems a simpler method is available using anonymous shared memory.This feature has been implemented in UNIX systems mapping the device `\dev\zero` orjust using the `MAP_ANONYMOUS` in a POSIX conformant `mmap` system call.This feature is wrapped in [*Boost.Interprocess] using the `anonymous_shared_memory()`function, which returns a `mapped_region` object holding an anonymous shared memorysegment that can be shared by related processes.Here is an example:[import ../example/doc_anonymous_shared_memory.cpp][doc_anonymous_shared_memory]Once the segment is created, a `fork()` call canbe used so that `region` is used to communicate two related processes.[endsect][section:windows_shared_memory Native windows shared memory]Windows operating system also offers shared memory, but the lifetime of thisshared memory is very different to kernel or filesystem lifetime. The shared memoryis created backed by the pagefile and it's automatically destroyed when the lastprocess attached to the shared memory is destroyed.Because of this reason, there is no effective way to simulate kernel or filesystempersistence using native windows shared memory and [*Boost.Interprocess] emulatesshared memory using memory mapped files. This assures portability between POSIXand Windows operating systems.However, accessing native windows shared memory is a common request of[*Boost.Interprocess] users because they want to access to shared memory created with other process that don't use[*Boost.Interprocess]. In order to manage the native windows shared memory[*Boost.Interprocess] offers the[classref boost::interprocess::windows_shared_memory windows_shared_memory] class.Windows shared memory creation is a bit different from portable shared memorycreation: the size of the segment must be specified when creating the object andcan't be specified through `truncate` like with the shared memory object.Take in care that when the last process attached to a shared memory is destroyed[*the shared memory is destroyed] so there is [*no persistency] with native windowsshared memory. Native windows shared memory has also another limitation: a process canopen and map the whole shared memory created by another process but it can't knowwhich is the size of that memory. This limitation is imposed by the Windows API sothe user must somehow transmit the size of the segment to processes opening thesegment.Let's repeat the same example presented for the portable shared memory object:A server process creates ashared memory object, maps it and initializes all the bytes to a value. After that, a client process opens the shared memory, maps it, and checksthat the data is correctly initialized. Take in care that [*if the server exits beforethe client connects to the shared memory the client connection will fail], becausethe shared memory segment is destroyed when no processes are attached to the memory.This is the server process:[import ../example/doc_windows_shared_memory.cpp][doc_windows_shared_memory]Now, before destroying the[classref boost::interprocess::windows_shared_memory windows_shared memory]object, launch the client process:[import ../example/doc_windows_shared_memory2.cpp][doc_windows_shared_memory2]As we can see, native windows shared memory needs synchronization to make surethat the shared memory won't be destroyed before the client is launched.[endsect][endsect][section:mapped_file Memory Mapped Files][section:mapped_file_what_is What is a memory mapped file?]

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?