您可以只分配共享内存段的一部分,将消息复制到该缓冲区,将共享内存该部分的偏移量发送到另一个进程,就完成了。让我们看一个例子
#include <boost/interprocess/managed_shared_memory.hpp> #include <cstdlib> //std::system #include <sstream> int main (int argc, char *[2] "MyName"[]) { using namespace boost::interprocess; if(argc == 1){ //Parent process //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MyName"); } ~shm_remove(){ shared_memory_object::remove("MyName"); } } remover; //Create a managed shared memory segment managed_shared_memory segment(create_only, "MyName", 65536); //Allocate a portion of the segment (raw memory) managed_shared_memory::size_type free_memory = segment.get_free_memory(); void * shptr = segment.allocate(1024/*bytes to allocate*/); //Check invariant if(free_memory <= segment.get_free_memory()) return 1; //An handle from the base address can identify any byte of the shared //memory segment even if it is mapped in different base addresses managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr); std::stringstream s; s << [2] "MyName"[0] << " " << handle; s << std::ends; //Launch child process if(0 != std::system(s.str().c_str())) return 1; //Check memory has been freed if(free_memory != segment.get_free_memory()) return 1; } else{ //Open managed segment managed_shared_memory segment(open_only, [2] "MyName"[2]); //An handle from the base address can identify any byte of the shared //memory segment even if it is mapped in different base addresses managed_shared_memory::handle_t handle = 0; //Obtain handle value std::stringstream s; s << [2] "MyName"[1]; s >> handle; //Get buffer local address from handle void *msg = segment.get_address_from_handle(handle); //Deallocate previously allocated memory segment.deallocate(msg); } return 0; }
您想要在共享内存段中创建对象,为它们指定字符串名称,以便任何其他进程都可以在不再需要这些对象时从段中查找、使用和删除它们。 示例
#include <boost/interprocess/managed_shared_memory.hpp> #include <cstdlib> //std::system #include <cstddef> #include <cassert> #include <utility> int main(int argc, char *[2] "MyName"[]) { using namespace boost::interprocess; typedef std::pair<double, int> MyType; if(argc == 1){ //Parent process //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MyName"); } ~shm_remove(){ shared_memory_object::remove("MyName"); } } remover; //Construct managed shared memory managed_shared_memory segment(create_only, "MyName", 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}... float float_initializer[3] = { 0.0, 1.0, 2.0 }; int int_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 process std::string s([2] "MyName"[0]); s += " child "; if(0 != std::system(s.c_str())) return 1; //Check child has destroyed all objects if(segment.find<MyType>("MyType array").first || segment.find<MyType>("MyType instance").first || segment.find<MyType>("MyType array from it").first) return 1; } else{ //Open managed shared memory managed_shared_memory segment(open_only, [2] "MyName"[2]); std::pair<MyType*, managed_shared_memory::size_type> res; //Find the array res = segment.find<MyType> ("MyType array"); //Length should be 10 if(res.second != 10) return 1; //Find the object res = segment.find<MyType> ("MyType instance"); //Length should be 1 if(res.second != 1) return 1; //Find the array constructed from iterators res = segment.find<MyType> ("MyType array from it"); //Length should be 3 if(res.second != 3) return 1; //We're done, delete all the objects segment.destroy<MyType>("MyType array"); segment.destroy<MyType>("MyType instance"); segment.destroy<MyType>("MyType array from it"); } return 0; }
Boost.Interprocess 提供了 offset_ptr 智能指针族,作为一种偏移指针,它存储偏移指针自身地址与指向对象地址之间的距离。当 offset_ptr 放置在共享内存段中时,即使该段在不同进程中映射到不同的基地址,它也可以安全地指向存储在同一共享内存段中的对象。
这允许将带有指针成员的对象放置在共享内存中。 例如,如果我们想在共享内存中创建一个链表
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/offset_ptr.hpp> using namespace boost::interprocess; //Shared memory linked list node struct list_node { offset_ptr<list_node> next; int value; }; int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MyName"); } ~shm_remove(){ shared_memory_object::remove("MyName"); } } remover; //Create shared memory managed_shared_memory segment(create_only, "MyName", //segment name 65536); //Create linked list with 10 nodes in shared memory offset_ptr<list_node> prev = 0, current, first; int i; 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; else prev->next = current; } //Communicate list to other processes //. . . //When done, destroy list for(current = first; current; /**/){ prev = current; current = current->next; segment.deallocate(prev.get()); } return 0; }
为了帮助处理基本数据结构,Boost.Interprocess 提供了诸如 vector、list、map 等容器,因此您可以像使用标准容器一样避免这些手动数据结构。
Boost.Interprocess 允许在共享内存和内存映射文件中创建复杂对象。 例如,我们可以在共享内存中构造类似 STL 的容器。 为此,我们只需要创建一个特殊的(托管)共享内存段,声明一个 Boost.Interprocess 分配器,并在共享内存中构造向量,就像它是任何其他对象一样。
允许在共享内存中创建这种复杂结构的类被称为 boost::interprocess::managed_shared_memory
,它很容易使用。 只需执行此示例,不带参数即可
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/container/vector.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <string> #include <cstdlib> //std::system using namespace boost::interprocess; //Define an STL compatible allocator of ints that allocates from the managed_shared_memory. //This allocator will allow placing containers in the segment typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator; //Alias a vector that uses the previous STL-like allocator so that allocates //its values from the segment typedef boost::container::vector<int, ShmemAllocator> MyVector; //Main function. For parent process argc == 1, for child process argc == 2 int main(int argc, char *[2] "MyName"[]) { if(argc == 1){ //Parent process //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MyName"); } ~shm_remove(){ shared_memory_object::remove("MyName"); } } remover; //Create a new segment with given name and size managed_shared_memory segment(create_only, "MyName", 65536); //Initialize shared memory STL-compatible allocator const ShmemAllocator alloc_inst (segment.get_segment_manager()); //Construct a vector named "MyVector" in shared memory with argument alloc_inst MyVector *myvector = segment.construct<MyVector>("MyVector")(alloc_inst); for(int i = 0; i < 100; ++i) //Insert data in the vector myvector->push_back(i); //Launch child process std::string s([2] "MyName"[0]); s += " child "; if(0 != std::system(s.c_str())) return 1; //Check child has destroyed the vector if(segment.find<MyVector>("MyVector").first) return 1; } else{ //Child process //Open the managed segment managed_shared_memory segment(open_only, [2] "MyName"[2]); //Find the vector using the c-string name MyVector *myvector = segment.find<MyVector>("MyVector").first; //Use vector in reverse order std::sort(myvector->rbegin(), myvector->rend()); //When done, destroy the vector from the segment segment.destroy<MyVector>("MyVector"); } return 0; }
父进程将创建一个特殊的共享内存类,该类允许轻松构建许多与名称关联的复杂数据结构。 父进程使用附加参数执行相同的程序,以便子进程打开共享内存并使用向量并擦除它。
就像向量一样,Boost.Interprocess 允许在共享内存和内存映射文件中创建映射。 唯一的区别是,与标准关联容器一样,当在构造函数中传递分配器时,Boost.Interprocess 的 map 也需要比较仿函数
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/container/map.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <functional> #include <utility> int main () { using namespace boost::interprocess; //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MyName"); } ~shm_remove(){ shared_memory_object::remove("MyName"); } } 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 resources managed_shared_memory segment(create_only,"MyName", 65536); //Note that map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>, //so the allocator must allocate that pair. typedef int KeyType; typedef float MappedType; typedef std::pair<const int, float> ValueType; //Alias an STL compatible allocator of for the map. //This allocator will allow to place containers //in managed shared memory segments typedef allocator<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. typedef boost::container::map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MyMap; //Initialize the shared memory STL-compatible allocator ShmemAllocator alloc_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 allocator MyMap *mymap = segment.construct<MyMap>("MyMap") //object name (std::less<int>() //first ctor parameter ,alloc_inst); //second ctor parameter //Insert data in the map for(int i = 0; i < 100; ++i){ mymap->insert(std::pair<const int, float>(i, (float)i)); } return 0; }
有关包含容器的容器的更高级示例,请参阅“容器的容器”部分。