我正在使用boost进程来共享内存,但是当我尝试使用boost :: interprocess :: scoped_lock尝试使用boost :: interprocess:named_mutex时很少出现分段错误。
我只运行编写程序进程。此进程拥有共享内存并且不会销毁它(除非应用程序正在关闭)。应用程序使用SharedDataCommon类(参见问题的底部)创建共享内存,该类包含所有boost内部工作,然后我调用write(),它尝试检索named_mutex但是它会出错。
分段错误发生在
中升压/间/同步/ POSIX / named_semaphore.hpp
第63行:
void wait()
{ semaphore_wait(mp_sem); } // seg faults here
就好像有人在应用程序运行时更改了对信号量的权限,但他们没有。是否有一个日志来检查在分段错误之前是否更改了权限?
在写入之前执行范围锁定时发生分段错误:
bool write(const std::vector<T>& vec, const bool clearFirst = false)
{
bip::scoped_lock<bip::named_mutex> lock(*sdc.mutex); // seg faults here
try
{
sdc.vec->reserve(sdc.vec->size() + vec.size());
}
catch(std::exception& e)
{
std::cout << "Not enough room to write elements" << std::endl;
return false;
}
if(clearFirst)
{
sdc.vec->clear();
}
for(const auto& item : vec)
{
sdc.vec->push_back(item);
}
sdc.cond_empty->notify_all();
return true;
}
sdc是一个封装boost :: interprocess组件的SharedDataCommon实例(见下文)。
我设置了临时设置umask,以便多个Linux用户可以读取共享内存。
template<typename T>
struct SharedDataCommon
{
using ShmemAllocator = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
using MyVector = bip::vector<T, ShmemAllocator>;
void initialise(const std::string& tag, const int numBytes, const bool ownMemory)
{
const std::string sharedMemoryName = tag + "_shared_memory";
const std::string sharedVectorName = tag + "_shared_vector";
const std::string sharedMutexName = tag + "_shared_mutex";
const std::string sharedCVName = tag + "_shared_cv";
tag_name = tag;
shared_memory_name = sharedMemoryName;
shared_mutex_name = sharedMutexName;
shared_vector_name = sharedVectorName;
shared_cv_name = sharedCVName;
destroy_memory = ownMemory;
if(ownMemory)
{
destroyMemory(tag);
}
createMemory(numBytes);
}
void createMemory(const int numBytes)
{
const mode_t old_umask = umask(0);
bip::permissions perm;
perm.set_unrestricted();
segment.reset(new bip::managed_shared_memory(bip::open_or_create, shared_memory_name.c_str(), numBytes, 0, perm));
mutex.reset(new bip::named_mutex(bip::open_or_create, shared_mutex_name.c_str(), perm));
const ShmemAllocator alloc_inst(segment->get_segment_manager());
vec = segment->find_or_construct<MyVector>(shared_vector_name.c_str())(alloc_inst);
cond_empty.reset(new bip::named_condition(bip::open_or_create, shared_cv_name.c_str(), perm));
umask(old_umask);
}
static void destroyMemory(const std::string& tag)
{
const std::string sharedMemoryName = tag + "_shared_memory";
const std::string sharedMutexName = tag + "_shared_mutex";
const std::string sharedCVName = tag + "_shared_cv";
bip::named_mutex::remove(sharedMutexName.c_str());
bip::named_condition::remove(sharedCVName.c_str());
bip::shared_memory_object::remove(sharedMemoryName.c_str());
}
~SharedDataCommon()
{
if(destroy_memory)
{
destroyMemory(tag_name);
}
}
std::shared_ptr<bip::named_mutex> mutex{nullptr};
MyVector* vec{nullptr};
std::shared_ptr<bip::managed_shared_memory> segment{nullptr};
std::shared_ptr<bip::named_condition> cond_empty;
bool destroy_memory{false};
std::string shared_vector_name;
std::string shared_mutex_name;
std::string shared_cv_name;
std::string shared_memory_name;
std::string tag_name;
};
我没有看到任何解释为什么问题会在某些时候发生的原因?
答案 0 :(得分:0)
当您可以在共享内存段中使用未命名的进程间同步原语时,为什么要使用所有这些单独的命名实体?参见例如Boost Interprocess share memory deletion, permissions and output files(第二个例子)。
这会立即消除检索所有共享对象和实际同步基元之间的竞争条件。
我唯一可以合理地看到在共享对象之外的是named_mutex
,因此您可以同步实际创建共享内存段。但是,看看你的代码看起来你没有做到这一点:
segment.reset(new bip::managed_shared_memory(bip::open_or_create, shared_memory_name.c_str(), numBytes, 0, perm));
mutex.reset(new bip::named_mutex(bip::open_or_create, shared_mutex_name.c_str(), perm));
在段之后创建互斥锁。现在,当您控制服务器和客户端启动的顺序时,这可能不是问题。但是,在这种情况下,显然不需要存在单独的命名互斥体。
同样令人担心的是你在没有任何同步的情况下破坏内存:
destroyMemory(tag);