Using boost library to store map in shared memory in c++

The interprocess package in the boost library can create complex types of data such as map in shared memory,
but std::map cannot be used. The main reason is that the absolute position of the pointer is used instead of the relative type
of boost map, vector, etc. , the specified allocator must be displayed, which is a lot more complicated.

An implementation of small and complete code: http://blog.csdn.net/dx2880/article/details/7315761


I referenced the wrong code in the process of learning, and took a lot of detours. The example posted here is mainly
to   separate the two parts of creating shared memory   and using data in shared memory into two programs, which is more in line with the general usage scenario (but in fact, the class definition should refer to a file):

Note: After testing, in Modify the Item class definition in the program that creates the shared memory, such as adding an int tmp; variable at the end, the program using the shared memory can still run normally without defining the Item class (but it is estimated that it is only applicable to map, vector Not as a container)



old rules, first look at the running results:
  • The first time you run the program that creates shared memory, it can be created normally;
  • The second time to run the program that created the shared memory, an exception is thrown because a shared memory of that name already exists
  • Run the program that uses shared memory for the first time, it can be used normally, and delete the shared memory
  • The first time you run a program that uses shared memory, an exception is thrown because the shared memory has been deleted





Finally, attach the complete program:
compile (note that you need to modify the path of the boost library)
boost_path="/home/colinliang/ThirdParty/boost_1_65_1"


#Note, -lrt must be at the end! ! ! Because managed_shared_mem_use_map.cpp uses this library, this writing order will change the linking order! ! !
#See https://stackoverflow.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



Create shared memory managed_shared_mem_use_map.cpp:
/** Use boost's map in shared memory, --- create shared memory
 The original code has a fatal error - the use of std::string!! in the stored Value will cause a segment fault
 * Code from: http://blog.csdn.net/nellson/article/details/50681103
 * Official documentation: http://www.boost.org/doc/libs/1_65_1/doc/html/interprocess.html
 *
 More complex examples, such as nested vectors in maps, and the use of boost::unordered_map, etc.
 See http://www.boost.org/doc/libs/1_65_1/doc/html/interprocess/allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_of_containers

 * Libraries that need to be added: https://stackoverflow.com/questions/7985236/c-boost-libraries-shared-memory-object-undefined-reference-to-shm-open
 * You need to add the rt library when linking, the method is 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; //Note that all variables that need to dynamically allocate memory can only be allocated with boost's 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); //Note that the size of shared memory must be specified here

		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); //You can construct two, but the names cannot be the same, otherwise an exception will be generated 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;

}




Use shared memory 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://stackoverflow.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;

}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326676187&siteId=291194637