欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c++中使用boost库在共享内存中存储map

程序员文章站 2022-07-04 13:35:16
...
boost库中的interprocess包可以在共享内存中创建map等复杂类型的数据,
但是不能用std::map,主要原因时其中的指针用的绝对位置,而非相对的
用boost的map,vector等类型,必须显示的指定allocator,因而复杂了不少。

代码小而全的一个实现:http://blog.csdn.net/dx2880/article/details/7315761


我在学习的过程中参考了错误的代码,走了不少弯路。这里贴出的示例主要是将
创建共享内存  和 使用共享内存中的数据  两部分分离成为了两个程序,更符合一般的使用场景(但其实类定义应该引用一个文件):

注意:经测试,在创建共享内存的程序中修改Item类定义,比如在最后新加一个int tmp; 变量,  使用共享内存的程序在不该把Item类定义的情况下仍然可以正常运行(但是估计只适用于map,vector作为容器时不行)



老规矩,先看运行结果:
  • 第一次运行创建共享内存的程序,可以正常创建;
  • 第二次运行创建共享内存的程序,因为已经存在该名字的共享内存,所以抛出异常
  • 第一次运行使用共享内存的程序,可以正常使用,并删除该共享内存
  • 第一次运行使用共享内存的程序,因为已经删除了该共享内存,所以抛出异常

c++中使用boost库在共享内存中存储map
            
    
    博客分类: C++ c++ 共享内存 



最后附上完整程序:
编译(注意需要修改boost库的路径)
boost_path="/home/colinliang/ThirdParty/boost_1_65_1"


#注意, -lrt必须放到最后!!! 因为managed_shared_mem_use_map.cpp 要用到该库,,这个书写顺序会改变链接顺序!!! 
#参见 https://*.com/questions/43052020/undefined-reference-to-shm-open-even-while-compiling-with-pthread-lrt
#It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
g++ -std=c++0x -L/lib   -I $boost_path managed_shared_mem_use_map.cpp -o exe_managed_shared_mem_use_map -pthread -lrt

g++ -std=c++0x -L/lib   -I $boost_path managed_shared_mem_use_map__read_existing.cpp -o exe_managed_shared_mem_use_map__read_existing -pthread -lrt



创建共享内存  managed_shared_mem_use_map.cpp:
/**  在共享内存中使用 boost 的map,  ---创建共享内存
 原始代码有个致命的错误——存储的Value中用来std::string!! 会导致segment fault
 * 代码来自: http://blog.csdn.net/nellson/article/details/50681103
 * 官方文档: http://www.boost.org/doc/libs/1_65_1/doc/html/interprocess.html
 *
 更复杂的例子,比如 map中嵌套vector, 以及 boost::unordered_map 的使用 等
 请参见 http://www.boost.org/doc/libs/1_65_1/doc/html/interprocess/allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_of_containers

 * 需要添加的库:https://*.com/questions/7985236/c-boost-libraries-shared-memory-object-undefined-reference-to-shm-open
 * 		链接时需要添加 rt 库,方法为  g++ -L /lib -lrt
 */

//#include <boost/interprocess/shared_memory_object.hpp>
//#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

#include <functional>
#include <cstdlib>
#include <utility>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <exception>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>  
#include <string>
#include <iostream>

using namespace boost::interprocess;
//Typedefs of allocators and containers
typedef managed_shared_memory::segment_manager segment_manager_t;
typedef allocator<void, segment_manager_t> void_allocator;
typedef allocator<int, segment_manager_t> int_allocator;
typedef vector<int, int_allocator> int_vector;
typedef allocator<int_vector, segment_manager_t> int_vector_allocator;
typedef vector<int_vector, int_vector_allocator> int_vector_vector;
typedef allocator<char, segment_manager_t> char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator> char_string;

using std::string;

class Item {
public:
	Item(const void_allocator& alloc, const char* name = "", int id = 0, int size = 0) :
			id(id), size(size), name(name, alloc) {
	}
	~Item() {
	}

	int id;
	int size;
	char_string name; //注意所有需要动态分配内存的变量,都只能用boost 的allocator进行内存分配
};

typedef char_string KeyType;
typedef Item MappedType;
typedef std::pair<const char_string, Item> ValueType;

typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;

typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MyMap;

int main() {
	try {
		// init
		managed_shared_memory segment(create_only, "SharedMemory", 65536); //注意这里必须指定共享内存的大小

		const void_allocator alloc_inst(segment.get_segment_manager());

		MyMap * mymap = segment.construct < MyMap > ("MyMap")(std::less<KeyType>(), alloc_inst);
		MyMap * mymap2 = segment.construct < MyMap > ("MyMap2")(std::less<KeyType>(), alloc_inst); //可以构建两个,但名称不能一样,否则会产生异常boost::interprocess_exception::library_error

		KeyType key(alloc_inst);
		Item v(alloc_inst);
		for (int i = 0; i < 5; ++i) {
			key = (std::string("n") + std::to_string(i)).c_str();
			v.id = i * 10;
			v.size = -i;
			v.name = (std::string("n") + std::to_string(i)).c_str();

			mymap->insert(ValueType(key, v));
		}

		MyMap* mymap_for_use = segment.find < MyMap > ("MyMap").first;
		long int r = segment.find < MyMap > ("MyMap").second;
		printf("result of find map in shared-memory: %ld\n", r);

		printf("key-values in shared memory: \n");
		for (MyMap::iterator it = mymap_for_use->begin(); it != mymap_for_use->end(); it++) {
			const auto& item = it->second;
			printf("\tkey: %s, item.id: %d, item.size: %d, item.name: %s\n", it->first.c_str(), item.id, item.size,
					item.name.c_str());
		}

		//shared_memory_object::remove("SharedMemory");
	} catch (const std::exception & e) {
		printf("Exception:%s\n", e.what());
		//shared_memory_object::remove("SharedMemory");
	}

	return 0;

}




使用共享内存 managed_shared_mem_use_map__read_existing.cpp:
/**  在共享内存中使用 boost 的map,  ----使用已经存在的共享内存
 原始代码有个致命的错误——存储的Value中用来std::string!! 会导致segment fault
 * 代码来自: http://blog.csdn.net/nellson/article/details/50681103
 * 官方文档: http://www.boost.org/doc/libs/1_65_1/doc/html/interprocess.html
 *
 更复杂的例子,请参见http://www.boost.org/doc/libs/1_65_1/doc/html/interprocess/allocators_containers.html
 中的“Containers of containers”一节

 * 需要添加的库:https://*.com/questions/7985236/c-boost-libraries-shared-memory-object-undefined-reference-to-shm-open
 * 		链接时需要添加 rt 库,方法为  g++ -L /lib -lrt
 */
//#include <boost/interprocess/shared_memory_object.hpp>
//#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

#include <functional>
#include <cstdlib>
#include <utility>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <exception>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>  
#include <string>
#include <iostream>

using namespace boost::interprocess;
//Typedefs of allocators and containers
typedef managed_shared_memory::segment_manager segment_manager_t;
typedef allocator<void, segment_manager_t> void_allocator;
typedef allocator<int, segment_manager_t> int_allocator;
typedef vector<int, int_allocator> int_vector;
typedef allocator<int_vector, segment_manager_t> int_vector_allocator;
typedef vector<int_vector, int_vector_allocator> int_vector_vector;
typedef allocator<char, segment_manager_t> char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator> char_string;

using std::string;

class Item {
public:
	Item(const void_allocator& alloc, const char* name = "", int id = 0, int size = 0) :
			id(id), size(size), name(name, alloc) {
	}
	~Item() {
	}

	int id;
	int size;
	char_string name; //注意所有需要动态分配内存的变量,都只能用boost 的allocator进行内存分配
};

typedef char_string KeyType;
typedef Item MappedType;
typedef std::pair<const char_string, Item> ValueType;

typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;

typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MyMap;

int main() {
	try {
		//shared_memory_object::remove("SharedMemory");
		// init
		managed_shared_memory segment(open_only, "SharedMemory");

		MyMap* mymap_for_use = segment.find < MyMap > ("MyMap").first;
		long int r = segment.find < MyMap > ("MyMap").second;
		printf("result of find map in shared-memory: %ld\n", r);

		printf("key-values in shared memory: \n");
		for (MyMap::iterator it = mymap_for_use->begin(); it != mymap_for_use->end(); it++) {
			const auto& item = it->second;
			printf("\tkey: %s, item.id: %d, item.size: %d, item.name: %s\n", it->first.c_str(), item.id, item.size,
					item.name.c_str());
		}
		

		shared_memory_object::remove("SharedMemory");
	} catch (const std::exception & e) {
		printf("Exception:%s\n", e.what());
		shared_memory_object::remove("SharedMemory");
	}

	return 0;

}

  • c++中使用boost库在共享内存中存储map
            
    
    博客分类: C++ c++ 共享内存 
  • 大小: 91 KB
相关标签: c++ 共享内存