interprocess.qbk
来自「Boost provides free peer-reviewed portab」· QBK 代码 · 共 1,625 行 · 第 1/5 页
QBK
1,625 行
std::size_t page_size = mapped_region::get_page_size();The operating system might also limit the number of mapped memory regions perprocess or per system.[endsect][endsect][section:mapped_region_object_limitations Limitations When Constructing Objects In Mapped Regions]When two processes create a mapped region of the same mappable object, two processescan communicate writing and reading that memory. A process could construct a C++ objectin that memory so that the second process can use it. However, a mapped region sharedby multiple processes, can't hold any C++ object, because not every class is readyto be a process-shared object, specially, if the mapped region is mapped in different address in each process.[section:offset_pointer Offset pointers instead of raw pointers]When placing objects in a mapped region and mappingthat region in different address in every process,raw pointers are a problem since they are only valid for theprocess that placed them there. To solve this, [*Boost.Interprocess] offersa special smart pointer that can be used instead of a raw pointer.So user classes containing raw pointers (or Boost smart pointers, thatinternally own a raw pointer) can't be safely placed in a process sharedmapped region. These pointers must be replaced with offset pointers, andthese pointers must point only to objects placed in the same mapped regionif you want to use these shared objects from different processes.Of course, a pointer placed in a mapped region shared between processes shouldonly point to an object of that mapped region. Otherwise, the pointer wouldpoint to an address that it's only valid one process and otherprocesses may crash when accessing to that address.[endsect][section:references_forbidden References forbidden]References suffer from the same problem as pointers (mainly because they are implemented as pointers).However, it is not possible to create a fully workable smart reference currently in C++ (for example,`operator .()` can't be overloaded). Because of this,if the user wants to put an object in shared memory, the object can't have any (smart or not) referenceas a member.References will only work if the mapped region is mapped in the samebase address in all processes sharing a memory segment.Like pointers, a reference placed in a mapped region should only pointto an object of that mapped region.[endsect][section:virtuality_limitation Virtuality forbidden]The virtual table pointer and the virtual tableare in the address space of the processthat constructs the object, so if we place a classwith a virtual function or virtual base class, the virtualpointer placed in shared memory will be invalid for other processesand they will crash.This problem is very difficult to solve, since each process needs adifferent virtual table pointer and the object that contains that pointeris shared across many processes. Even if we map the mapped region inthe same address in every process, the virtual table can be in a differentaddress in every process. To enable virtual functions for objectsshared between processes, deep compiler changes are needed and virtualfunctions would suffer a performance hit. That's why[*Boost.Interprocess] does not have any plan to support virtual functionand virtual inheritance in mapped regions shared between processes.[endsect][section:statics_warning Be careful with static class members]Static members of classes are global objects shared by all instances of the class. Because of this, staticmembers are implemented as global variables in processes.When constructing a class with static members, each processhas its own copy of the static member, so updating a staticmember in one process does not change the value of the staticmember the another process. So be careful with these classes. Staticmembers are not dangerous if they are just constant variables initializedwhen the process starts, but they don't change at all (for example,when used like enums) and their value is the same for all processes.[endsect][endsect][endsect][section:offset_ptr Mapping Address Independent Pointer: offset_ptr]When creating shared memory and memory mapped files to communicate twoprocesses the memory segment can be mapped in a different address in each process:[c++] #include<boost/interprocess/shared_memory_object.hpp> // ... using boost::interprocess; //Open a shared memory segment shared_memory_object shm_obj (open_only //open or create ,"shared_memory" //name ,read_only //read-only mode ); //Map the whole shared memory mapped_region region ( shm //Memory-mappable object , read_write //Access mode ); //This address can be different in each process void *addr = region.get_address();This makes the creation of complex objects in mapped regions difficult: a C++class instance placed in a mapped region might have a pointer pointing toanother object also placed in the mapped region. Since the pointer stores an absolute address, that address is only valid for the process that placed the object there unless all processes map the mapped region in the sameaddress.To be able to simulate pointers in mapped regions, users must use [*offsets](distance between objects) instead of absolute addresses. The offset betweentwo objects in a mapped region is the same for any process that maps themapped region, even if that region is placed in different base addresses.To facilitate the use of offsets, [*Boost.Interprocess] offers [classref boost::interprocess::offset_ptr offset_ptr].[classref boost::interprocess::offset_ptr offset_ptr]wraps all the background operations needed to offer a pointer-like interface. The class interface is inspired in Boost Smart Pointers and this smart pointerstores the offset (distance in bytes)between the pointee's address and it's own `this` pointer.Imagine a structure in a common32 bit processor:[c++] struct structure { int integer1; //The compiler places this at offset 0 in the structure offset_ptr<int> ptr; //The compiler places this at offset 4 in the structure int integer2; //The compiler places this at offset 8 in the structure }; //... structure s; //Assign the address of "integer1" to "ptr". //"ptr" will store internally "-4": // (char*)&s.integer1 - (char*)&s.ptr; s.ptr = &s.integer1; //Assign the address of "integer2" to "ptr". //"ptr" will store internally "4": // (char*)&s.integer2 - (char*)&s.ptr; s.ptr = &s.integer2;One of the big problems of `offset_ptr` is the representation of the null pointer. The null pointer can't be safely represented like an offset, since the absolute address 0is always outside of the mapped region. Due to the fact that the segment can be mappedin a different base address in each process the distance between the address 0and `offset_ptr` is different for every process.Some implementations choose the offset 0 (that is, an `offset_ptr`pointing to itself) as the null pointer pointer representationbut this is not valid for many use cases since many times structures like linked lists or nodes from STL containerspoint to themselves (the end node in an empty container, for example) and 0 offset value is needed. An alternative is to store, in addition to the offset, a booleanto indicate if the pointer is null. However, this increments the size of thepointer and hurts performance.In consequence,[classref boost::interprocess::offset_ptr offset_ptr] defines offset 1as the null pointer, meaning that this class [*can't] point to the byteafter its own ['this] pointer:[c++] using namespace boost::interprocess; offset_ptr<char> ptr; //Pointing to the next byte of it's own address //marks the smart pointer as null. ptr = (char*)&ptr + 1; //ptr is equal to null assert(!ptr); //This is the same as assigning the null value... ptr = 0; //ptr is also equal to null assert(!ptr);In practice, this limitation is not important, since a user almost neverwants to point to this address.[classref boost::interprocess::offset_ptr offset_ptr]offers all pointer-like operations andrandom_access_iterator typedefs, so it can be used in STL algorithms requiring random access iterators and detected via traits.For more information about the members and operations of the class, see[classref boost::interprocess::offset_ptr offset_ptr reference].[endsect][section:synchronization_mechanisms Synchronization mechanisms][section:synchronization_mechanisms_overview Synchronization mechanisms overview]As mentioned before, the ability to shared memory between processes through memorymapped files or shared memory objects is not very useful if the access to that memory can't be effectively synchronized. This is the same problem that happens withthread-synchronization mechanisms, where heap memory and global variables areshared between threads, but the access to these resources needs to be synchronizedtypically through mutex and condition variables. [*Boost.Threads] implements thesesynchronization utilities between threads inside the same process. [*Boost.Interprocess]implements similar mechanisms to synchronize threads from different processes.[section:synchronization_mechanisms_named_vs_anonymous Named And Anonymous Synchronization Mechanisms][*Boost.Interprocess] presents two types of synchronization objects:* [*Named utilities]: When two processes want to create an object of such type, both processes must ['create] or ['open] an object using the same name. This is similar to creating or opening files: a process creates a file with using a `fstream` with the name ['filename] and another process opens that file using another `fstream` with the same ['filename] argument. [*Each process uses a different object to access to the resource, but both processes are using the same underlying resource].* [*Anonymous utilities]: Since these utilities have no name, two processes must share [*the same object] through shared memory or memory mapped files. This is similar to traditional thread synchronization objects: [*Both processes share the same object]. Unlike thread synchronization, where global variables and heap memory is shared between threads of the same process, sharing objects between two threads from different process can be only possible through mapped regions that map the same mappable resource (for example, shared memory or memory mapped files).Each type has it's own advantages and disadvantages:* Named utilities are easier to handle for simple synchronization tasks, since both process don't have to create a shared memory region and construct the synchronization mechanism there. * Anonymous utilities can be serialized to disk when using memory mapped objects obtaining automatic persistence of synchronization utilities. One could construct a synchronization utility in a memory mapped file, reboot the system, map the file again, and use the synchronization utility again without any problem. This can't be achieved with named synchronization utilities.The main interface difference between named and anonymous utilities are the constructors.Usually anonymous utilities have only one constructor, whereas the named utilities haveseveral constructors whose first argument is a special type that requests creation, opening or opening or creation of the underlying resource:[c++] using namespace boost::interprocess; //Create the synchronization utility. If it previously //exists, throws an error NamedUtility(create_only, ...) //Open the synchronization utility. If it does not previously //exist, it's created. NamedUtility(open_or_create, ...) //Open the synchronization utility. If it does not previously //exist, throws an error. NamedUtility(open_only, ...)On the other hand the anonymous synchronization utility can onlybe created and the processes must synchronize using other mechanismswho creates the utility:[c++] using namespace boost::interprocess; //Create the synchronization utility. AnonymousUtility(...)[endsect][section:synchronization_mechanisms_types Types Of Synchronization Mechanisms]Apart from its named/anonymous nature, [*Boost.Interprocess] presents the followingsynchronization utilities:* Mutexes (named and anonymous)* Condition variables (named and anonymous)* Semaphores (named and anonymous)* Upgradable mutexes* File locks[endsect][endsect][section:mutexes Mutexes][section:mutexes_whats_a_mutex What's A Mutex?]['Mutex] stands for [*mut]ual [*ex]clusion and it's the most basic form of
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?