提高进程间互斥和检查放弃

我需要围绕一个硬件进行进程间同步。 因为这个代码需要在Windows和Linux上工作,所以我使用了Boost Interprocess互斥体。 一切正常,接受我的方法检查放弃互斥体。 这可能会发生,所以我必须做好准备。

我在testing中放弃了互斥锁,当然,当我使用scoped_locklocking互斥锁时,进程会无限期地阻塞。 我想通过在scoped_lock上使用超时机制来解决这个问题(因为花费了很多时间用于Google的方法来解决这个问题并没有多大的好处,但是由于可移植性的原因,boost并没有做太多的工作)。

不用再后悔了,下面是我所拥有的:

#include <boost/interprocess/sync/named_recursive_mutex.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> typedef boost::interprocess::named_recursive_mutex MyMutex; typedef boost::interprocess::scoped_lock<MyMutex> ScopedLock; MyMutex* pGate = reinterpret_cast<MyMutex*>(new MyMutex(boost::interprocess::open_or_create, "MutexName"); { // ScopedLock lock(*pGate); // this blocks indefinitely boost::posix_time::ptime timeout(boost::posix_time::microsec_clock::local_time() + boost::posix_time::seconds(10)); ScopedLock lock(*pGate, timeout); // a 10 second timeout that returns immediately if the mutex is abandoned ????? if(!lock.owns()) { delete pGate; boost::interprocess::named_recursive_mutex::remove("MutexName"); pGate = reinterpret_cast<MyMutex*>(new MyMutex(boost::interprocess::open_or_create, "MutexName"); } } 

那至less是这个想法。 三个有趣的点:

  • 当我使用超时对象,并且互斥体被放弃时,ScopedLock控制器将无限期地阻塞。 这是预料之中的。
  • 当我使用超时,并且互斥体被放弃时,ScopedLock立即返回并告诉我它不拥有互斥体。 好吧,也许这是正常的,但为什么它不等待我说的10秒?
  • 当互斥体没有被放弃 ,并且我使用超时时,ScopedLock ctor仍然立即返回,告诉我它不能locking或取得互斥体的所有权,并且通过去除互斥体并重新制作它的动作。 这完全不是我想要的。

那么,我在使用这些对象时错过了什么? 也许它正在盯着我,但我看不到它,所以我在寻求帮助。

我还要提一下,由于这个硬件是如何工作的,如果这个过程在10秒内不能获得互斥体的所有权,这个互斥体就被放弃了。 事实上,我可以等待50或60毫秒,但10秒钟是一个很好的“圆”数量的慷慨。

我正在使用Visual Studio 2010在Windows 7上进行编译。

谢谢,安迪

当我不使用超时对象,并且互斥体被放弃时,ScopedLock控制器将无限期地阻塞。 这是预料之中的

对于你的问题最好的解决方案是如果提高了强大的互斥体的支持。 但是Boost目前不支持强大的互斥锁。 只有一个计划强大的互斥体的计划,因为只有Linux本身的支持。 图书馆作者Ion Gaztanaga仍在计划这个模拟。 检查这个链接关于一个可能的黑客入侵rubs互斥量到提升库: http ://boost.2283326.n4.nabble.com/boost-interprocess-gt-1-45-robust-mutexes-td3416151.html

同时,您可能会尝试在共享段中使用原子变量。

也看看这个stackoverflow条目: 我如何获得一个废弃的boost :: interprocess :: interprocess_mutex的所有权?

当我使用超时,并且互斥体被放弃时,ScopedLock立即返回并告诉我它不拥有互斥体。 好吧,也许这是正常的,但为什么它不等待我说的10秒?

这很奇怪,你不应该得到这种行为。 但是:定时锁可能是以try lock的形式实现的。 请查阅此文档: http : //www.boost.org/doc/libs/1_53_0/doc/html/boost/interprocess/scoped_lock.html#idp57421760-bb这意味着,定时锁的实现可能会在内部引发异常然后返回false。

 inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { sync_handles &handles = windows_intermodule_singleton<sync_handles>::get(); //This can throw winapi_mutex_functions mut(handles.obtain_mutex(this->id_)); return mut.timed_lock(abs_time); } 

可能,由于互斥体被放弃,无法获得手柄。

当互斥体没有被放弃,并且我使用超时时,ScopedLock ctor仍然立即返回,告诉我它不能锁定或取得互斥体的所有权,并且通过去除互斥体并重新制作它的动作。 这完全不是我想要的。

我不确定这个,但我认为这个命名互斥体是通过使用共享内存来实现的。 如果您正在使用Linux,请检查文件/ dev / shm / MutexName。 在Linux中,无论是否通过例如boost :: interprocess :: named_recursive_mutex :: remove删除了文件本身,文件描述符都保持有效。

检查BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKINGBOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS编译标志。 定义代码中的第一个符号以强制进程间互斥锁超时,第二个符号定义超时持续时间。

我帮助他们加入到图书馆来解决废弃的互斥问题。 由于依赖于简单互斥而不是定时互斥的许多进程间结构(如message_queue),所以有必要添加它。 将来可能会有一个更强大的解决方案,但是这个解决方案对我的进程间需求来说工作得很好。

对不起,目前我无法帮助你处理你的代码。 有东西在那里工作不正确。

BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING不太好。 它抛出一个异常,并没有太大的帮助。 要解决例外的行为,我写了这个宏。 它适用于通用目的。 在这个例子中使用了named_mutex。 该宏创建一个超时范围的锁,如果出于特殊原因无法获取该锁,则将其解锁。 这样程序可以稍后再次锁定,不会立即冻结或崩溃。

 #define TIMEOUT 1000 #define SAFELOCK(pMutex) \ boost::posix_time::ptime wait_time \ = boost::posix_time::microsec_clock::universal_time() \ + boost::posix_time::milliseconds(TIMEOUT); \ boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(*pMutex, wait_time); \ if(!lock.owns()) { \ pMutex->unlock(); } 

但即使这样也不是最佳的,因为现在要锁定的代码会一次解锁。 这可能会导致问题。 但是,您可以轻松地扩展宏。 例如,只有在lock.owns()为true时才运行代码。