Вы можете просто выделить часть разделяемого сегмента памяти, скопировать сообщение в этот буфер, отправить смещение этой части совместно используемой памяти в другой процесс. Давайте посмотрим на пример:
#include<boost/interprocess/managed_shared_memory.hpp>#include<cstdlib>//std::system#include<sstream>intmain(intargc,char*argv[]){usingnamespaceboost::interprocess;if(argc==1){//Parent process//Remove shared memory on construction and destructionstructshm_remove{shm_remove(){shared_memory_object::remove("MySharedMemory");}~shm_remove(){shared_memory_object::remove("MySharedMemory");}}remover;//Create a managed shared memory segmentmanaged_shared_memorysegment(create_only,"MySharedMemory",65536);//Allocate a portion of the segment (raw memory)managed_shared_memory::size_typefree_memory=segment.get_free_memory();void*shptr=segment.allocate(1024/*bytes to allocate*/);//Check invariantif(free_memory<=segment.get_free_memory())return1;//An handle from the base address can identify any byte of the shared//memory segment even if it is mapped in different base addressesmanaged_shared_memory::handle_thandle=segment.get_handle_from_address(shptr);std::stringstreams;s<<argv[0]<<" "<<handle;s<<std::ends;//Launch child processif(0!=std::system(s.str().c_str()))return1;//Check memory has been freedif(free_memory!=segment.get_free_memory())return1;}else{//Open managed segmentmanaged_shared_memorysegment(open_only,"MySharedMemory");//An handle from the base address can identify any byte of the shared//memory segment even if it is mapped in different base addressesmanaged_shared_memory::handle_thandle=0;//Obtain handle valuestd::stringstreams;s<<argv[1];s>>handle;//Get buffer local address from handlevoid*msg=segment.get_address_from_handle(handle);//Deallocate previously allocated memorysegment.deallocate(msg);}return0;}
Вы хотите создавать объекты в сегменте общей памяти, давая им имя строки, чтобы любой другой процесс мог найти, использовать и удалить их из сегмента, когда объекты больше не нужны. Пример:
#include<boost/interprocess/managed_shared_memory.hpp>#include<cstdlib>//std::system#include<cstddef>#include<cassert>#include<utility>intmain(intargc,char*argv[]){usingnamespaceboost::interprocess;typedefstd::pair<double,int>MyType;if(argc==1){//Parent process//Remove shared memory on construction and destructionstructshm_remove{shm_remove(){shared_memory_object::remove("MySharedMemory");}~shm_remove(){shared_memory_object::remove("MySharedMemory");}}remover;//Construct managed shared memorymanaged_shared_memorysegment(create_only,"MySharedMemory",65536);//Create an object of MyType initialized to {0.0, 0}MyType*instance=segment.construct<MyType>("MyType instance")//name of the object(0.0,0);//ctor first argument//Create an array of 10 elements of MyType initialized to {0.0, 0}MyType*array=segment.construct<MyType>("MyType array")//name of the object[10]//number of elements(0.0,0);//Same two ctor arguments for all objects//Create an array of 3 elements of MyType initializing each one//to a different value {0.0, 0}, {1.0, 1}, {2.0, 2}...floatfloat_initializer[3]={0.0,1.0,2.0};intint_initializer[3]={0,1,2};MyType*array_it=segment.construct_it<MyType>("MyType array from it")//name of the object[3]//number of elements(&float_initializer[0]//Iterator for the 1st ctor argument,&int_initializer[0]);//Iterator for the 2nd ctor argument//Launch child processstd::strings(argv[0]);s+=" child ";if(0!=std::system(s.c_str()))return1;//Check child has destroyed all objectsif(segment.find<MyType>("MyType array").first||segment.find<MyType>("MyType instance").first||segment.find<MyType>("MyType array from it").first)return1;}else{//Open managed shared memorymanaged_shared_memorysegment(open_only,"MySharedMemory");std::pair<MyType*,managed_shared_memory::size_type>res;//Find the arrayres=segment.find<MyType>("MyType array");//Length should be 10if(res.second!=10)return1;//Find the objectres=segment.find<MyType>("MyType instance");//Length should be 1if(res.second!=1)return1;//Find the array constructed from iteratorsres=segment.find<MyType>("MyType array from it");//Length should be 3if(res.second!=3)return1;//We're done, delete all the objectssegment.destroy<MyType>("MyType array");segment.destroy<MyType>("MyType instance");segment.destroy<MyType>("MyType array from it");}return0;}
Boost.Interprocessпредлагает семейство умных указателей offset_ptr в качестве офсетного указателя, который хранит расстояние между адресом самого офсетного указателя и адресом заостренного объекта. Когда offset_ptr помещается в сегмент общей памяти, он может безопасно указывать объекты, хранящиеся в одном сегменте общей памяти, даже если сегмент отображается в разных базовых адресах в разных процессах.
Это позволяет размещать объекты с указателями в общей памяти. Например, если мы хотим создать связанный список в общей памяти:
#include<boost/interprocess/managed_shared_memory.hpp>#include<boost/interprocess/offset_ptr.hpp>usingnamespaceboost::interprocess;//Shared memory linked list nodestructlist_node{offset_ptr<list_node>next;intvalue;};intmain(){//Remove shared memory on construction and destructionstructshm_remove{shm_remove(){shared_memory_object::remove("MySharedMemory");}~shm_remove(){shared_memory_object::remove("MySharedMemory");}}remover;//Create shared memorymanaged_shared_memorysegment(create_only,"MySharedMemory",//segment name65536);//Create linked list with 10 nodes in shared memoryoffset_ptr<list_node>prev=0,current,first;inti;for(i=0;i<10;++i,prev=current){current=static_cast<list_node*>(segment.allocate(sizeof(list_node)));current->value=i;current->next=0;if(!prev)first=current;elseprev->next=current;}//Communicate list to other processes//. . .//When done, destroy listfor(current=first;current;/**/){prev=current;current=current->next;segment.deallocate(prev.get());}return0;}
Чтобы помочь с базовыми структурами данных,Boost.Interprocessпредлагает контейнеры, такие как вектор, список, карта, поэтому вы можете избежать этих структур данных вручную, как и в стандартных контейнерах.
Boost.Interprocessпозволяет создавать сложные объекты в общей памяти и картированных файлах памяти. Например, мы можем создавать STL-подобные контейнеры в общей памяти. Для этого нам просто нужно создать специальный (управляемый) сегмент совместно используемой памяти, объявитьBoost.Interprocessаллокатором и построить вектор в совместно используемой памяти, если это был какой-либо другой объект.
Класс, который позволяет использовать эти сложные структуры в общей памяти, называется<boost::interprocess::managed_shared_memory>. Выполните этот пример без аргументов:
#include<boost/interprocess/managed_shared_memory.hpp>#include<boost/interprocess/containers/vector.hpp>#include<boost/interprocess/allocators/allocator.hpp>#include<string>#include<cstdlib>//std::systemusingnamespaceboost::interprocess;//Define an STL compatible allocator of ints that allocates from the managed_shared_memory.//This allocator will allow placing containers in the segmenttypedefallocator<int,managed_shared_memory::segment_manager>ShmemAllocator;//Alias a vector that uses the previous STL-like allocator so that allocates//its values from the segmenttypedefvector<int,ShmemAllocator>MyVector;//Main function. For parent process argc == 1, for child process argc == 2intmain(intargc,char*argv[]){if(argc==1){//Parent process//Remove shared memory on construction and destructionstructshm_remove{shm_remove(){shared_memory_object::remove("MySharedMemory");}~shm_remove(){shared_memory_object::remove("MySharedMemory");}}remover;//Create a new segment with given name and sizemanaged_shared_memorysegment(create_only,"MySharedMemory",65536);//Initialize shared memory STL-compatible allocatorconstShmemAllocatoralloc_inst(segment.get_segment_manager());//Construct a vector named "MyVector" in shared memory with argument alloc_instMyVector*myvector=segment.construct<MyVector>("MyVector")(alloc_inst);for(inti=0;i<100;++i)//Insert data in the vectormyvector->push_back(i);//Launch child processstd::strings(argv[0]);s+=" child ";if(0!=std::system(s.c_str()))return1;//Check child has destroyed the vectorif(segment.find<MyVector>("MyVector").first)return1;}else{//Child process//Open the managed segmentmanaged_shared_memorysegment(open_only,"MySharedMemory");//Find the vector using the c-string nameMyVector*myvector=segment.find<MyVector>("MyVector").first;//Use vector in reverse orderstd::sort(myvector->rbegin(),myvector->rend());//When done, destroy the vector from the segmentsegment.destroy<MyVector>("MyVector");}return0;}
Родительский процесс создаст специальный общий класс памяти, который позволит легко построить множество сложных структур данных, связанных с именем. Родительский процесс выполняет ту же программу с дополнительным аргументом, поэтому детский процесс открывает общую память и использует вектор и стирает его.
Как и вектор,Boost.Interprocessпозволяет создавать карты в общей памяти и отображаемые в памяти файлы. Разница лишь в том, что, подобно стандартным ассоциативным контейнерам,Boost.Interprocessна карте также нужен сравнительный функтор, когда распределитель передается в конструкторе:
#include<boost/interprocess/managed_shared_memory.hpp>#include<boost/interprocess/containers/map.hpp>#include<boost/interprocess/allocators/allocator.hpp>#include<functional>#include<utility>intmain(){usingnamespaceboost::interprocess;//Remove shared memory on construction and destructionstructshm_remove{shm_remove(){shared_memory_object::remove("MySharedMemory");}~shm_remove(){shared_memory_object::remove("MySharedMemory");}}remover;//Shared memory front-end that is able to construct objects//associated with a c-string. Erase previous shared memory with the name//to be used and create the memory segment at the specified address and initialize resourcesmanaged_shared_memorysegment(create_only,"MySharedMemory"//segment name,65536);//segment size in bytes//Note that map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,//so the allocator must allocate that pair.typedefintKeyType;typedeffloatMappedType;typedefstd::pair<constint,float>ValueType;//Alias an STL compatible allocator of for the map.//This allocator will allow to place containers//in managed shared memory segmentstypedefallocator<ValueType,managed_shared_memory::segment_manager>ShmemAllocator;//Alias a map of ints that uses the previous STL-like allocator.//Note that the third parameter argument is the ordering function//of the map, just like with std::map, used to compare the keys.typedefmap<KeyType,MappedType,std::less<KeyType>,ShmemAllocator>MyMap;//Initialize the shared memory STL-compatible allocatorShmemAllocatoralloc_inst(segment.get_segment_manager());//Construct a shared memory map.//Note that the first parameter is the comparison function,//and the second one the allocator.//This the same signature as std::map's constructor taking an allocatorMyMap*mymap=segment.construct<MyMap>("MyMap")//object name(std::less<int>()//first ctor parameter,alloc_inst);//second ctor parameter//Insert data in the mapfor(inti=0;i<100;++i){mymap->insert(std::pair<constint,float>(i,(float)i));}return0;}
Для более продвинутого примера, включающего контейнеры контейнеров, см. разделКонтейнеры контейнеров.
Статья Quick Guide for the Impatient раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 16. Boost.Interprocess может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.