二.快速指南(为急于想了解Boost.Interprocess的朋友)
使用共享内存做为一个匿名内存块池 创建命名共享内存对象 为共享内存使用一个偏移智能指针 在共享内存中创建容器(vector) 在共享内存中创建映射表(map) |
使用共享内存做为一个匿名内存块池
你可以仅分配共享内存段的一部分,拷贝消息至那块缓冲区中,然后发送那部分共享内存的偏移量至另外一个进程即可。示例如下:
- #include <boost/interprocess/managed_shared_memory.hpp>
- #include <cstdlib> //std::system
- #include <sstream>
- int main (int argc, char *argv[])
- {
- using namespace boost::interprocess;
- if(argc == 1){ //Parent process
- //Remove shared memory on construction anddestruction
- struct shm_remove
- {
- shm_remove() { shared_memory_object::remove("MySharedMemory");}
- ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
- }remover;
- //Create a managed shared memory segment
- managed_shared_memory segment(create_only,"MySharedMemory",65536);
- //Allocate a portion of the segment (rawmemory)
- managed_shared_memory::size_type free_memory = segment.get_free_memory();
- void * shptr = segment.allocate(1024/*bytes toallocate*/);
- //Check invariant
- if(free_memory <= segment.get_free_memory())
- return 1;
- //An handle from the base address canidentify any byte of the shared
- //memory segment even if it is mapped indifferent base addresses
- managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr);
- std::stringstream s;
- s<< argv[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,"MySharedMemory");
- //An handle from the base address canidentify any byte of the shared
- //memory segment even if it is mapped indifferent base addresses
- managed_shared_memory::handle_t handle = 0;
- //Obtain handle value
- std::stringstream s; s<< argv[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;
- }
创建命名共享内存对象
你可以在共享内存段中创建对象,给它们string类型的名字以便其他进程能够找到它们,使用它们,并且当对象不再使用时从内存段中删除它们。示例如下:
[cpp] view plain copy
- #include <boost/interprocess/managed_shared_memory.hpp>
- #include <cstdlib> //std::system
- #include <cstddef>
- #include <cassert>
- #include <utility>
- int main(int argc, char *argv[])
- {
- 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("MySharedMemory"); }
- ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
- } remover;
- //Construct managed shared memory
- managed_shared_memory segment(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}...
- 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(argv[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, "MySharedMemory");
- 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置于共享内存段中时,它能安全的指向这块共享内存段中的对象,甚至当内存段在不同的进程映射到不同的基地址时也能正常工作。
这使得带指针成员的对象能够放置在共享内存中。例如,如果我们想在共享内存中创建一个链表:
[cpp] view plain copy
- #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("MySharedMemory"); }
- ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
- } remover;
- //Create shared memory
- managed_shared_memory segment(create_only,
- "MySharedMemory", //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的容器,因此你能避免这些数据结构手册,就像使用标准容器一样。
在共享内存中创建容器(vector)
Boost.Interprocess允许在共享内存和内存映射文件中创建复杂的对象。例如,我们可以在共享内存中创建类STL容器。为了做到这点,我们仅需创建一个特殊(控制)的共享内存片段,申明一个Boost.Interprocess分配器然后创建像其他对象一样在共享内存中创建vector.
这个允许在共享内存中创建复杂结构的类是 boost::interprocess::managed_shared_memory,它使用起来非常简单。只要不带参数执行下面这个例子:
[cpp] view plain copy
- #include <boost/interprocess/managed_shared_memory.hpp>
- #include <boost/interprocess/containers/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 vector<int, ShmemAllocator> MyVector;
- //Main function. For parent process argc == 1, for child process argc == 2
- int main(int argc, char *argv[])
- {
- if(argc == 1){ //Parent process
- //Remove shared memory on construction and destruction
- struct shm_remove
- {
- shm_remove() { shared_memory_object::remove("MySharedMemory"); }
- ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
- } remover;
- //Create a new segment with given name and size
- managed_shared_memory segment(create_only, "MySharedMemory", 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(argv[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, "MySharedMemory");
- //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;
- };
父进程将创建一个特殊的共享内存类,它允许许多具名复杂数据结构的构建。子进程(译注:原文这里误写为父进程)带参数的执行同一个程序,打开共享内存,使用vector并且删除它。
在共享内存中创建映射表(map)
与vector一样,Boost.Interprocess允许在共享内存和内存映射文件中创建映射表。唯一的不同点在于,与标准关联容器一样,当分配器传入到构造函数中时,Boost.Interprocess的map也需要定义比较函数:
[cpp] view plain copy
- #include <boost/interprocess/managed_shared_memory.hpp>
- #include <boost/interprocess/containers/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("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 resources
- managed_shared_memory segment
- (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.
- 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 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;
- }
更多例子(包含容器的容器),可参考章节“容器的容器”