[关闭]
@Pigmon 2019-01-02T08:59:05.000000Z 字数 14131 阅读 3238

boost::interprocess 共享内存

C++


0. 链接

https://theboostcpplibraries.com/boost.interprocess
https://www.boost.org/doc/libs/1_67_0/doc/html/interprocess.html

1. Makefile

  1. all:
  2. g++ test.cpp -pthread -o test -lrt
  3. clean:
  4. rm -r test

-lrt 必须在最后,否则link错误。原因不详。

2. Basic Shared Memory

TODO

3. Managed Shared Memory

3.1 存取一个整数

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <iostream>
  3. using namespace boost::interprocess;
  4. int main()
  5. {
  6. // 先删除
  7. bool ret = shared_memory_object::remove("My_SHM");
  8. std::cout << std::boolalpha << ret << std::endl;
  9. // 构造 managed shared memory 对象
  10. managed_shared_memory managed_shm(open_or_create, "My_SHM", 1024);
  11. int *i = managed_shm.construct<int>("My_Age")(109);
  12. std::cout << *i << '\n';
  13. // 按名字读取
  14. std::pair<int *, std::size_t> p = managed_shm.find<int>("My_Age");
  15. if (p.first)
  16. std::cout << *p.first << ":" << p.second << std::endl;
  17. }

3.2 存取一个 Vector

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <iostream>
  4. using namespace boost::interprocess;
  5. typedef boost::interprocess::vector<int> IntVec;
  6. int main()
  7. {
  8. int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  9. IntVec vec(arr, arr + sizeof(arr) / sizeof(int));
  10. // 先删除
  11. shared_memory_object::remove("My_SHM_Array");
  12. // 构建 managed shared memory
  13. managed_shared_memory managed_shm(open_or_create, "My_SHM_Array", 1024);
  14. // 将 vec 存储至 shared memory, 或者使用 find_or_construct
  15. IntVec *vec_shm = managed_shm.construct<IntVec>("Numbers")(vec);
  16. std::cout << (*vec_shm)[2] << '\n';
  17. // 读取
  18. std::pair<IntVec*, std::size_t> p = managed_shm.find<IntVec>("Numbers");
  19. if (p.first)
  20. {
  21. std::cout << (*(p.first))[8] << '\n';
  22. std::cout << p.second << '\n';
  23. }
  24. }

3.3 捕获内存分配异常

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <iostream>
  3. using namespace boost::interprocess;
  4. int main()
  5. {
  6. try
  7. {
  8. shared_memory_object::remove("My_SHM_Array");
  9. managed_shared_memory managed_shm(open_or_create, "My_SHM_Array", 1024);
  10. int *i = managed_shm.construct<int>("Numbers")[4096](99);
  11. }
  12. catch (boost::interprocess::bad_alloc &ex)
  13. {
  14. std::cerr << ex.what() << '\n';
  15. }
  16. }

3.4 删除共享内存对象

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <iostream>
  3. using namespace boost::interprocess;
  4. int main()
  5. {
  6. shared_memory_object::remove("My_SHM_Array");
  7. managed_shared_memory managed_shm(open_or_create, "My_SHM_Array", 1024);
  8. int *i = managed_shm.find_or_construct<int>("Numbers")(99);
  9. std::cout << *i << '\n';
  10. managed_shm.destroy<int>("Numbers");
  11. std::pair<int *, std::size_t> p = managed_shm.find<int>("Numbers");
  12. std::cout << p.first << '\n';
  13. }

3.5 存储 string

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/allocators/allocator.hpp>
  3. #include <boost/interprocess/containers/string.hpp>
  4. #include <iostream>
  5. using namespace boost::interprocess;
  6. int main()
  7. {
  8. shared_memory_object::remove("My_SHM_String");
  9. managed_shared_memory managed_shm(open_or_create, "My_SHM_String", 1024);
  10. typedef allocator<char, managed_shared_memory::segment_manager> CharAllocator;
  11. typedef basic_string<char, std::char_traits<char>, CharAllocator> AString;
  12. AString *s = managed_shm.find_or_construct<AString>("MyString")("Hello!", managed_shm.get_segment_manager());
  13. s->insert(5, ", world");
  14. std::cout << *s << '\n';
  15. }

3.6 原子操作

需要在操作过程中起到类似加锁的功能,即在操作过程中不受其他进程干扰时使用。
其他进程必须也使用 atomic_func 来访问这个共享内存对象才能保证这个机制。

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <functional>
  3. #include <iostream>
  4. using namespace boost::interprocess;
  5. /// 原子操作本体
  6. void construct_objects(managed_shared_memory &managed_shm)
  7. {
  8. managed_shm.construct<int>("A_Int_Number")(99);
  9. managed_shm.construct<float>("A_Float_Number")(3.14);
  10. }
  11. int main()
  12. {
  13. shared_memory_object::remove("My_SHM_Obj");
  14. managed_shared_memory managed_shm(open_or_create, "My_SHM_Obj", 1024);
  15. // 绑定 原子操作 和 managed_shared_memory对象
  16. auto atomic_construct = std::bind(construct_objects, std::ref(managed_shm));
  17. managed_shm.atomic_func(atomic_construct);
  18. std::cout << *managed_shm.find<int>("A_Int_Number").first << '\n';
  19. std::cout << *managed_shm.find<float>("A_Float_Number").first << '\n';
  20. }

3.7 在两个进程中用共享内存通信一个 Vector

Server:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <string>
  5. //#include <cstdlib> //std::system
  6. #include <iostream>
  7. using namespace boost::interprocess;
  8. //Define an STL compatible allocator of ints that allocates from the managed_shared_memory.
  9. //This allocator will allow placing containers in the segment
  10. typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
  11. typedef vector<int, ShmemAllocator> MyVector;
  12. int main(int argc, char *argv[])
  13. {
  14. shared_memory_object::remove("MySharedMemory");
  15. managed_shared_memory segment(create_only, "MySharedMemory", 65536);
  16. //Initialize shared memory STL-compatible allocator
  17. const ShmemAllocator alloc_inst(segment.get_segment_manager());
  18. MyVector *myvector = segment.construct<MyVector>("MyVector")(alloc_inst);
  19. for (int i = 0; i < 100; ++i)
  20. myvector->push_back(i);
  21. return 0;
  22. };

Client:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <string>
  5. #include <iostream>
  6. using namespace boost::interprocess;
  7. //Define an STL compatible allocator of ints that allocates from the managed_shared_memory.
  8. //This allocator will allow placing containers in the segment
  9. typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
  10. typedef vector<int, ShmemAllocator> MyVector;
  11. int main(int argc, char *argv[])
  12. {
  13. managed_shared_memory segment(open_only, "MySharedMemory");
  14. // Test read
  15. MyVector *vec_test = segment.find<MyVector>("MyVector").first;
  16. for (auto it = vec_test->begin(); it != vec_test->end(); it++)
  17. std::cout << (*it) << ",";
  18. std::cout << std::endl;
  19. return 0;
  20. };

4 同步

4.1 anonymous mutex

使用 boost::interprocess::interprocess_mutex,可以保证被 mutex guard 的量可以由所有进程访问,因为其是存储在共享内存中的 (与boost::interprocess::named_mutex不同,后者由操作系统管理,并不是共享内存机制,无法跨进程访问)。

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  3. #include <iostream>
  4. using namespace boost::interprocess;
  5. int main()
  6. {
  7. // bool ret = shared_memory_object::remove("shm");
  8. // std::cout << std::boolalpha << ret << std::endl;
  9. managed_shared_memory managed_shm(open_or_create, "shm", 1024);
  10. int *i = managed_shm.find_or_construct<int>("TheNumber")(80);
  11. interprocess_mutex *mtx = managed_shm.find_or_construct<interprocess_mutex>("mtx")();
  12. mtx->lock();
  13. ++(*i);
  14. std::cout << *i << '\n';
  15. mtx->unlock();
  16. }

4.2 用同步方式生产消费一个Vector

Server:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  5. #include <boost/interprocess/sync/interprocess_condition.hpp>
  6. #include <boost/interprocess/sync/scoped_lock.hpp>
  7. #include <string>
  8. //#include <cstdlib> //std::system
  9. #include <iostream>
  10. using namespace boost::interprocess;
  11. typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
  12. typedef vector<int, ShmemAllocator> MyVector;
  13. int main(int argc, char *argv[])
  14. {
  15. shared_memory_object::remove("MySharedMemory");
  16. managed_shared_memory segment(create_only, "MySharedMemory", 65536);
  17. interprocess_mutex *mtx = segment.find_or_construct<interprocess_mutex>("mtx")();
  18. interprocess_condition *cnd = segment.find_or_construct<interprocess_condition>("cnd")();
  19. scoped_lock<interprocess_mutex> lock{*mtx};
  20. //Initialize shared memory STL-compatible allocator
  21. const ShmemAllocator alloc_inst(segment.get_segment_manager());
  22. MyVector *myvector = segment.construct<MyVector>("MyVector")(alloc_inst);
  23. // 每次获取锁后,更新vector内容。
  24. // 然后放开,等 Client 得到后再更新
  25. int counter = 0;
  26. while (counter < 10)
  27. {
  28. counter++;
  29. myvector->clear();
  30. for (int i = 0; i < 10; ++i)
  31. myvector->push_back(i * counter);
  32. cnd->notify_all();
  33. cnd->wait(lock);
  34. }
  35. cnd->notify_all();
  36. shared_memory_object::remove("MySharedMemory");
  37. return 0;
  38. };

Client:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  5. #include <boost/interprocess/sync/interprocess_condition.hpp>
  6. #include <boost/interprocess/sync/scoped_lock.hpp>
  7. #include <string>
  8. #include <iostream>
  9. using namespace boost::interprocess;
  10. typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
  11. typedef vector<int, ShmemAllocator> MyVector;
  12. int main(int argc, char *argv[])
  13. {
  14. managed_shared_memory segment(open_only, "MySharedMemory");
  15. interprocess_mutex *mtx = segment.find_or_construct<interprocess_mutex>("mtx")();
  16. interprocess_condition *cnd = segment.find_or_construct<interprocess_condition>("cnd")();
  17. scoped_lock<interprocess_mutex> lock{*mtx};
  18. MyVector *vec_test = segment.find<MyVector>("MyVector").first;
  19. // 得到数据后放开等待 Server 更新 vector
  20. int counter = 0;
  21. while (counter < 10)
  22. {
  23. counter++;
  24. for (auto it = vec_test->begin(); it != vec_test->end(); it++)
  25. std::cout << (*it) << ",";
  26. std::cout << std::endl;
  27. cnd->notify_all();
  28. cnd->wait(lock);
  29. }
  30. cnd->notify_all();
  31. return 0;
  32. };

4.3 自定义类型的 Vector

只是 Allocator 和上面不一样,应对类似 ESR 毫米波雷达 CAN 数据的情形。
Server:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  5. #include <boost/interprocess/sync/interprocess_condition.hpp>
  6. #include <boost/interprocess/sync/scoped_lock.hpp>
  7. #include <string>
  8. //#include <cstdlib> //std::system
  9. #include <iostream>
  10. using namespace boost::interprocess;
  11. struct some_data
  12. {
  13. int id;
  14. double info;
  15. };
  16. typedef allocator<some_data, managed_shared_memory::segment_manager> ShmemAllocator;
  17. typedef vector<some_data, ShmemAllocator> MyVector;
  18. int main(int argc, char *argv[])
  19. {
  20. shared_memory_object::remove("MySharedMemory");
  21. managed_shared_memory segment(create_only, "MySharedMemory", 65536);
  22. interprocess_mutex *mtx = segment.find_or_construct<interprocess_mutex>("mtx")();
  23. interprocess_condition *cnd = segment.find_or_construct<interprocess_condition>("cnd")();
  24. scoped_lock<interprocess_mutex> lock{*mtx};
  25. //Initialize shared memory STL-compatible allocator
  26. const ShmemAllocator alloc_inst(segment.get_segment_manager());
  27. MyVector *myvector = segment.construct<MyVector>("MyVector")(alloc_inst);
  28. int counter = 0;
  29. while (counter < 10)
  30. {
  31. counter++;
  32. myvector->clear();
  33. for (int i = 0; i < 10; ++i)
  34. {
  35. some_data data{i * counter, 0.2 * counter};
  36. myvector->push_back(data);
  37. }
  38. cnd->notify_all();
  39. cnd->wait(lock);
  40. }
  41. cnd->notify_all();
  42. shared_memory_object::remove("MySharedMemory");
  43. return 0;
  44. };

Client:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  5. #include <boost/interprocess/sync/interprocess_condition.hpp>
  6. #include <boost/interprocess/sync/scoped_lock.hpp>
  7. #include <string>
  8. #include <iostream>
  9. using namespace boost::interprocess;
  10. struct some_data
  11. {
  12. int id;
  13. double info;
  14. };
  15. typedef allocator<some_data, managed_shared_memory::segment_manager> ShmemAllocator;
  16. typedef vector<some_data, ShmemAllocator> MyVector;
  17. int main(int argc, char *argv[])
  18. {
  19. managed_shared_memory segment(open_only, "MySharedMemory");
  20. interprocess_mutex *mtx = segment.find_or_construct<interprocess_mutex>("mtx")();
  21. interprocess_condition *cnd = segment.find_or_construct<interprocess_condition>("cnd")();
  22. scoped_lock<interprocess_mutex> lock{*mtx};
  23. MyVector *vec_test = segment.find<MyVector>("MyVector").first;
  24. int counter = 0;
  25. while (counter < 10)
  26. {
  27. counter++;
  28. for (auto it = vec_test->begin(); it != vec_test->end(); it++)
  29. std::cout << "<" << (*it).id << "," << (*it).info << ">";
  30. std::cout << std::endl;
  31. cnd->notify_all();
  32. cnd->wait(lock);
  33. }
  34. cnd->notify_all();
  35. return 0;
  36. };

4.4 Vector 为成员的自定义类型列表

类似激光雷达点云数据的情形
Server:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  5. #include <boost/interprocess/sync/interprocess_condition.hpp>
  6. #include <boost/interprocess/sync/scoped_lock.hpp>
  7. #include <string>
  8. //#include <cstdlib> //std::system
  9. #include <iostream>
  10. using namespace boost::interprocess;
  11. // 即便一个简单的Vector,也必须这样用 allocator 初始化,否则 Client 找不到?
  12. typedef allocator<double, managed_shared_memory::segment_manager> DoubleAllocator;
  13. typedef vector<double, DoubleAllocator> dVec;
  14. struct some_data
  15. {
  16. int id;
  17. dVec info;
  18. };
  19. typedef allocator<some_data, managed_shared_memory::segment_manager> ShmemAllocator;
  20. typedef vector<some_data, ShmemAllocator> MyVector;
  21. int main(int argc, char *argv[])
  22. {
  23. shared_memory_object::remove("MySharedMemory");
  24. managed_shared_memory segment(create_only, "MySharedMemory", 65536);
  25. interprocess_mutex *mtx = segment.find_or_construct<interprocess_mutex>("mtx")();
  26. interprocess_condition *cnd = segment.find_or_construct<interprocess_condition>("cnd")();
  27. scoped_lock<interprocess_mutex> lock{*mtx};
  28. //Initialize shared memory STL-compatible allocator
  29. const ShmemAllocator alloc_inst(segment.get_segment_manager());
  30. MyVector *myvector = segment.construct<MyVector>("MyVector")(alloc_inst);
  31. int counter = 0;
  32. while (counter < 10)
  33. {
  34. counter++;
  35. myvector->clear();
  36. for (int i = 0; i < 10; ++i)
  37. {
  38. std::stringstream s;
  39. s << "info_" << counter << "_" << i;
  40. const DoubleAllocator alloc_inst(segment.get_segment_manager());
  41. dVec *vec = segment.construct<dVec>(s.str().c_str())(alloc_inst);;
  42. vec->push_back(0.2 * counter);
  43. vec->push_back(2.0 * counter);
  44. some_data data{i * counter, *vec};
  45. myvector->push_back(data);
  46. }
  47. cnd->notify_all();
  48. cnd->wait(lock);
  49. }
  50. cnd->notify_all();
  51. shared_memory_object::remove("MySharedMemory");
  52. return 0;
  53. };

Client:

  1. #include <boost/interprocess/managed_shared_memory.hpp>
  2. #include <boost/interprocess/containers/vector.hpp>
  3. #include <boost/interprocess/allocators/allocator.hpp>
  4. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  5. #include <boost/interprocess/sync/interprocess_condition.hpp>
  6. #include <boost/interprocess/sync/scoped_lock.hpp>
  7. #include <string>
  8. #include <iostream>
  9. using namespace boost::interprocess;
  10. typedef allocator<double, managed_shared_memory::segment_manager> DoubleAllocator;
  11. typedef vector<double, DoubleAllocator> dVec;
  12. struct some_data
  13. {
  14. int id;
  15. dVec info;
  16. };
  17. typedef allocator<some_data, managed_shared_memory::segment_manager> ShmemAllocator;
  18. typedef vector<some_data, ShmemAllocator> MyVector;
  19. int main(int argc, char *argv[])
  20. {
  21. managed_shared_memory segment(open_only, "MySharedMemory");
  22. interprocess_mutex *mtx = segment.find_or_construct<interprocess_mutex>("mtx")();
  23. interprocess_condition *cnd = segment.find_or_construct<interprocess_condition>("cnd")();
  24. scoped_lock<interprocess_mutex> lock{*mtx};
  25. MyVector *vec_test = segment.find<MyVector>("MyVector").first;
  26. int counter = 0;
  27. while (counter < 10)
  28. {
  29. counter++;
  30. for (auto it = vec_test->begin(); it != vec_test->end(); it++)
  31. std::cout << "<" << (*it).id << ":" << (*it).info[0] << "," << (*it).info[1] << ">";
  32. std::cout << std::endl;
  33. cnd->notify_all();
  34. cnd->wait(lock);
  35. }
  36. cnd->notify_all();
  37. return 0;
  38. };
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注