提升进程间互斥锁崩溃而不是等待锁定?
Posted
技术标签:
【中文标题】提升进程间互斥锁崩溃而不是等待锁定?【英文标题】:Boost interprocess mutex crashes instead of waiting on a lock? 【发布时间】:2015-10-18 12:24:39 【问题描述】:我已经在这工作了好几天(甚至在 boost 论坛上的 posted)并且能够让第二个进程识别锁定的互斥锁似乎不起作用。请帮忙。这是代码:
一个常见的头文件:SharedObject.hpp
#ifndef SHAREDOBJECT_HPP
#define SHAREDOBJECT_HPP
#include <iostream>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <time.h>//for sleep
//--------for mutexes
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <boost/interprocess/sync/upgradable_lock.hpp>
#define MUTEX_SHARED_MEMORY_NAME "NavSharedMemoryMutex"
#define DATAOUTPUT "OutputFromObject"
#define INITIAL_MEM 650000
using namespace std;
namespace bip = boost::interprocess;
class SharedMutex
private:
typedef bip::interprocess_upgradable_mutex upgradable_mutex_type;
mutable upgradable_mutex_type mutex;
volatile int counter;
public:
void lockWithReadLock() const bip::sharable_lock<upgradable_mutex_type> lock(mutex);
void lockWithWriteLock() bip::scoped_lock<upgradable_mutex_type> lock(mutex);
;
//-------------------------------------- SharedMemoryObject
class SharedObject
public:
SharedMutex* sharedMutex;
;
typedef bip::allocator<SharedObject, bip::managed_shared_memory::segment_manager> ShmemAllocator;
typedef bip::list<SharedObject, ShmemAllocator> SharedMemData;
#endif /* SHAREDOBJECT_HPP */
这是第一个程序:
#include "SharedObject.hpp"
int main()
//-----------Create shared memory and put shared object into it
bip::managed_shared_memory* seg;
SharedMemData *sharedMemOutputList;
bip::shared_memory_object::remove(DATAOUTPUT);
seg = new bip::managed_shared_memory(bip::create_only, DATAOUTPUT, INITIAL_MEM);
const ShmemAllocator alloc_inst(seg->get_segment_manager());
sharedMemOutputList = seg->construct<SharedMemData>("TrackOutput")(alloc_inst);
std::size_t beforeAllocation = seg->get_free_memory();
std::cout<<"\nBefore allocation = "<< beforeAllocation <<"\n";
SharedObject temp;
sharedMemOutputList->push_back(temp);
//-------------------Create a shared memory for holding a mutex
bip::shared_memory_object::remove(MUTEX_SHARED_MEMORY_NAME);//BUG: If another program also removes this, then there won't be any shared memory remaining. This problem has to be handled better. This is not the right way to deal with shared mutexes.
bip::shared_memory_object shm(bip::create_only, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
shm.truncate(sizeof (SharedMutex)); //Allocate memory in shared memory for the mutex
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
new (region.get_address()) SharedMutex; // Construct the SharedMutex using placement new
temp.sharedMutex = static_cast<SharedMutex *> (region.get_address()); //Store the mutex object address for future reference
std::cout<<"Program 1: Before first locking -------------------------- 1 v\n";
temp.sharedMutex->lockWithWriteLock();
const unsigned int SLEEP_TIME_IN_SECOND = 60;
std::cout<<"Program 1: sleep for "<< SLEEP_TIME_IN_SECOND << "\n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout<<"Program 1: Finished sleeping\n";
std::cout<<"Program 1: unlocked -------------------------------------- 1 ^\n";
seg->destroy<SharedMemData>("TrackOutput");
delete seg;
return 0;
//main
这是第二个程序:
#include "SharedObject.hpp"
#define CREATE_SEPARATE_MUTEX
int main()
bip::managed_shared_memory segment(bip::open_only, DATAOUTPUT); //Open the managed segment
SharedMemData* sharedMemoryTrackOutputList = segment.find<SharedMemData>("TrackOutput").first; //Find the list using the c-string name
assert(sharedMemoryTrackOutputList);
std::cout << "SharedMemoryData address found at = " << (void *) sharedMemoryTrackOutputList << "\n";
std::cout << "size = " << sharedMemoryTrackOutputList->size() << "\n";
SharedMemData::iterator iter = sharedMemoryTrackOutputList->begin();
#ifndef CREATE_SEPARATE_MUTEX
//-------------------Create a shared memory for holding a mutex
bip::shared_memory_object shm(bip::open_or_create, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
shm.truncate(sizeof (SharedMutex)); //Allocate memory in shared memory for the mutex
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
new (region.get_address()) SharedMutex; // Construct the SharedMutex using placement new
(*iter).sharedMutex = static_cast<SharedMutex *> (region.get_address()); //Store the mutex object address for future reference
#endif
std::cout<<"Program 2: Before first locking -------------------------- 1 v\n";
(*iter).sharedMutex->lockWithWriteLock();
const unsigned int SLEEP_TIME_IN_SECOND = 1;
std::cout<<"Program 2: sleep for "<< SLEEP_TIME_IN_SECOND << "\n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout<<"Program 2: Finished sleeping\n";
std::cout<<"Program 2: unlocked -------------------------------------- 1 ^\n";
return 0;
//main
程序 1 运行良好。 程序 2 给出了这个输出:
SharedMemoryData address found at = 0x7f0a4c2b8118
size = 1
Program 2: Before first locking -------------------------- 1 v
terminate called after throwing an instance of 'boost::interprocess::lock_exception'
what(): boost::interprocess::lock_exception
Aborted (core dumped)
我首先运行 program1,它锁定互斥体并保持锁定 60 秒。在那段时间里,我运行程序 2 来查看它是否在等待锁,但它崩溃了。如何让程序 2 在互斥体上等待,直到程序 1 完成写入共享内存?
【问题讨论】:
erm "这个帖子还没有被邮件列表接受。" - 所以看起来你实际上并没有在 boost 邮件列表中发布任何内容。您必须先成为会员。 【参考方案1】:好的,您的代码有一些问题。
SharedMutex
存储在不同的内存区域,在第二个程序中没有映射。
映射区域可以有不同的基地址,因此原始指针在此环境中不起作用。请改用boost::interprocess::offset_ptr
。但是请注意,它们适用于指向同一内存段的指针,因此将您的 SharedMutex 和 SharedObject 放在同一段中是有意义的(或者使用named_mutex
代替所有这些)。
在 main1 中,将temp
复制到共享内存在修改成员变量sharedMutex
。您应该确保在共享内存中您的指针 (offset_ptr
-to-be) 实际上是有效的。
当您尝试使用 lockWithWriteLock
函数锁定 scoped_lock
时,锁定会在函数退出时立即解锁。因此,一旦您解决了上述所有问题并摆脱了崩溃,您仍然不会获得预期的输出 - 您的代码逻辑应该更改。
和代码:
sharedObject.hpp
#ifndef SHAREDOBJECT_HPP
#define SHAREDOBJECT_HPP
#include <iostream>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <time.h>//for sleep
//--------for mutexes
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <boost/interprocess/sync/upgradable_lock.hpp>
#define MUTEX_SHARED_MEMORY_NAME "NavSharedMemoryMutex"
#define DATAOUTPUT "OutputFromObject"
#define INITIAL_MEM 650000
using namespace std;
namespace bip = boost::interprocess;
class SharedMutex
public:
typedef bip::interprocess_upgradable_mutex upgradable_mutex_type;
mutable upgradable_mutex_type mutex;
;
//-------------------------------------- SharedMemoryObject
class SharedObject
public:
SharedMutex* sharedMutex;
;
typedef bip::allocator<SharedObject, bip::managed_shared_memory::segment_manager> ShmemAllocator;
typedef bip::list<SharedObject, ShmemAllocator> SharedMemData;
#endif /* SHAREDOBJECT_HPP */
程序1:
#include "SharedObject.hpp"
int main()
//-----------Create shared memory and put shared object into it
bip::managed_shared_memory* seg;
SharedMemData *sharedMemOutputList;
bip::shared_memory_object::remove(DATAOUTPUT);
seg = new bip::managed_shared_memory(bip::create_only, DATAOUTPUT, INITIAL_MEM);
const ShmemAllocator alloc_inst(seg->get_segment_manager());
sharedMemOutputList = seg->construct<SharedMemData>("TrackOutput")(alloc_inst);
SharedObject temp;
//-------------------Create a shared memory for holding a mutex
bip::shared_memory_object::remove(MUTEX_SHARED_MEMORY_NAME);//BUG: If another program also removes this, then there won't be any shared memory remaining. This problem has to be handled better. This is not the right way to deal with shared mutexes.
bip::shared_memory_object shm(bip::open_or_create, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
shm.truncate(sizeof(SharedMutex)); //Allocate memory in shared memory for the mutex
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
new (region.get_address()) SharedMutex; // Construct the SharedMutex using placement new
temp.sharedMutex = static_cast<SharedMutex *> (region.get_address()); //Store the mutex object address for future reference
std::cout << "Region address " << region.get_address() << "\n";
sharedMemOutputList->push_back(temp);
//initiate scope for scoped mutex
std::cout << "Program 1: Going to do 1st locking -------------------------- 1 v\n";
bip::scoped_lock<bip::interprocess_upgradable_mutex> lock(temp.sharedMutex->mutex);
const unsigned int SLEEP_TIME_IN_SECOND = 10;
std::cout<<"Program 1: locked. Now sleep for "<< SLEEP_TIME_IN_SECOND << "\n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout << "Program 1: Finished sleeping\n";
std::cout << "Program 1: unlocked ----------------------------------------- 1 ^\n";
//seg->destroy<SharedMemData>("TrackOutput");delete seg;
return 0;
//main
和程序 2:
#include "SharedObject.hpp"
#define READ_LOCK_TESTING
#ifndef READ_LOCK_TESTING
#define WRITE_LOCK_TESTING
#endif
int main()
bip::managed_shared_memory segment(bip::open_only, DATAOUTPUT); //Open the managed segment
SharedMemData* sharedMemoryTrackOutputList = segment.find<SharedMemData>("TrackOutput").first; //Find the list using the c-string name
assert(sharedMemoryTrackOutputList);
std::cout << "SharedMemoryData address found at = " << (void *)sharedMemoryTrackOutputList << "\n";
std::cout << "size = " << sharedMemoryTrackOutputList->size() << "\n";
SharedMemData::iterator iter = sharedMemoryTrackOutputList->begin();
bip::shared_memory_object shm(bip::open_or_create, MUTEX_SHARED_MEMORY_NAME, bip::read_write);
bip::mapped_region region(shm, bip::read_write); // Map the whole shared memory into this process.
std::cout << "Region address " << region.get_address() << "\n";
//Initiate the scope for the scoped mutex
std::cout << "Program 2: Going to do 2nd locking -------------------------- 2 v\n";
iter->sharedMutex = static_cast<SharedMutex*>(region.get_address());
#ifdef WRITE_LOCK_TESTING
bip::scoped_lock<bip::interprocess_upgradable_mutex> lock((*iter).sharedMutex->mutex);//write lock
#endif
#ifdef READ_LOCK_TESTING
bip::sharable_lock<bip::interprocess_upgradable_mutex> lock((*iter).sharedMutex->mutex);//read lock
#endif
const unsigned int SLEEP_TIME_IN_SECOND = 10;
std::cout << "Program 2: locked. Now sleep for " << SLEEP_TIME_IN_SECOND << "\n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout << "Program 2: Finished sleeping\n";
std::cout << "Program 2: unlocked ------------------------------------------ 2 ^\n";
return 0;
//main
【讨论】:
非常感谢罗斯蒂斯拉夫。我之前也尝试过named_mutex
,但没有成功。也许我实施错了。实际的代码示例在这里会有所帮助,因为我尝试了很多东西并参考了 boost 示例代码,但锁定不起作用。这是我在这里发布的最后手段。您是否可以使用工作代码更新您的答案?我相信它也会帮助更多的程序员。
@Nav 这是工作代码。与您的不同,看看差异。 offset_ptr
没有在那里使用,但我想你会明白的。 main1main2main.h
谢谢@Rostislav。非常感激。我已将代码添加到您的答案中。我还必须添加一些异常处理,因为如果程序运行有点乱,它往往会崩溃,因为它找不到共享内存或进程间异常说它找不到文件或目录.我会处理的。您对清除有关如何解决锁定的疑问的帮助非常大。【参考方案2】:
Rostislav 曾建议使用命名互斥锁,因此也仅举一个命名互斥锁的示例(尽管我想要读写器锁,而这些锁似乎不支持命名互斥锁......不过我可能错了)。
计划 1:
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>
int main ()
using namespace boost::interprocess;
try
struct mutex_remove
mutex_remove() named_mutex::remove("fstream_named_mutex");
~mutex_remove() named_mutex::remove("fstream_named_mutex");
remover;
//Open or create the named mutex
named_mutex mutex(open_or_create, "fstream_named_mutex");
std::cout<<"gonna lock\n";
scoped_lock<named_mutex> lock(mutex);
const unsigned int SLEEP_TIME_IN_SECOND = 10;
std::cout<<"Program 1: locked. Now sleep for "<< SLEEP_TIME_IN_SECOND << "\n";
sleep(SLEEP_TIME_IN_SECOND);
std::cout<<"unlocked\n";
catch(interprocess_exception &ex)
std::cout << ex.what() << std::endl;
return 1;
return 0;
计划 2:
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>
int main ()
using namespace boost::interprocess;
try
//Open or create the named mutex
named_mutex mutex(open_or_create, "fstream_named_mutex");
std::cout<<"gonna lock\n";
scoped_lock<named_mutex> lock(mutex);
const unsigned int SLEEP_TIME_IN_SECOND = 5;
std::cout<<"Program 2: locked. Now sleep for "<< SLEEP_TIME_IN_SECOND << "\n";
sleep(SLEEP_TIME_IN_SECOND);
catch(interprocess_exception &ex)
std::cout << ex.what() << std::endl;
return 1;
return 0;
【讨论】:
以上是关于提升进程间互斥锁崩溃而不是等待锁定?的主要内容,如果未能解决你的问题,请参考以下文章