// // Purpose: Play arround with shared memory and the permissions to allocate it // #include // shmget,... #include #include #include // errno #include // strerror #include // system #include #include #include static const int invalid_shm_id = -1; static const int invalid_shm_pointer = -1; static const int shm_key = 0x12345; static const int shm_size = 0x1000; static const std::string shm_key_for_boost = boost::lexical_cast(shm_key); static const int shm_boost_margin = 0x100; boost::uint8_t * shm_create_unix(int & shm_id) { // // create global shared memory and get an id of it // (identified by the given key) // shm_id = shmget(shm_key, shm_size, 0600 | IPC_CREAT | IPC_EXCL); if (shm_id == invalid_shm_id) { std::cerr << "Could not get global shared memory for key=" << shm_key << ": " << strerror(errno) << std::endl; return 0; } // // attach the global shared memory // (associated with the given id, not the key) // boost::uint8_t * shm = static_cast(shmat(shm_id, static_cast(0), 0)); if (shm == reinterpret_cast(invalid_shm_pointer)) { std::cerr << "Could not attach global shared memory for id=" << boost::lexical_cast(shm_id) << ", key=" << boost::lexical_cast(shm_key) << ": " << strerror(errno) << std::endl; return 0; } return shm; } void shm_free_unix(boost::uint8_t * shm, int shm_id) { int ret = shmdt(shm); if (ret == -1) { std::cerr << "Detaching of shared memory (0x" << std::hex << shm << std::dec << ") failed. id=" << shm_id << ": " << strerror(errno) << std::endl; return; } ret = shmctl(shm_id, IPC_RMID, NULL); if (ret != 0) { std::cerr << "Deleting of shared memory failed. id=" << boost::lexical_cast(shm_id) << ": " << strerror(errno) << std::endl; } } boost::uint8_t * shm_create_boost() { using namespace boost::interprocess; //A special shared memory from which we are //able to allocate raw memory buffers. //First remove any old shared memory of the same name, create //the shared memory segment and initialize needed resources shared_memory_object::remove(shm_key_for_boost.c_str()); void * shm = 0; try { // boost also needs some private space in the shared memory managed_shared_memory segment(create_only, shm_key_for_boost.c_str(), shm_size+shm_boost_margin); //Allocate a portion of the segment shm = segment.allocate(shm_size); } catch(...) { shared_memory_object::remove(shm_key_for_boost.c_str()); throw; } return static_cast(shm); } void shm_free_boost(boost::uint8_t * shm) { using namespace boost::interprocess; try { managed_shared_memory segment(open_only, shm_key_for_boost.c_str()); segment.deallocate(shm); } catch(...) { shared_memory_object::remove(shm_key_for_boost.c_str()); throw; } shared_memory_object::remove(shm_key_for_boost.c_str()); } int main(int argc, char * argv[]) { if (argc <= 1) { std::cout << "unix way:" << std::endl; int shm_id = invalid_shm_id; boost::uint8_t * const shm = shm_create_unix(shm_id); std::cout << "Got shm=" << static_cast(shm) << std::endl; system("ipcs -m"); shm_free_unix(shm, shm_id); } else { std::cout << "Boost way:" << std::endl; boost::uint8_t * const shm = shm_create_boost(); std::cout << "Got shm=" << static_cast(shm) << std::endl; system("ipcs -m"); shm_free_boost(shm); } return 0; }