提升managed_shared_memory find()方法永远停留在互斥锁上

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了提升managed_shared_memory find()方法永远停留在互斥锁上相关的知识,希望对你有一定的参考价值。

我有以下程序,这是它应该做的:

  • 打开/创建共享内存段
  • 在该托管共享内存段上调用find()以查找对象
  • 如果没有找到,则实例化它
  • 如果找到,只需转储内容

我通过以下方式测试它:

  • 在一个窗口中运行该程序的一个实例
  • 它创建共享内存段并实例化该对象
  • 永远等待(不确定是否需要这个,只是添加它以确保linux一旦程序退出就不会释放共享内存)
  • 运行同一程序的另一个实例,并期望它找到对象(这就是它被卡住的地方) class data_store { public: data_store(uint32_t id, const char *name, bool safe) { id_ = id; strncpy(name_, name, sizeof(name_)); safe_ = safe; } ~data_store() {} uint32_t id(void) const { return id_; } const char *name(void) const { return name_; } private: char name_[32]; bool safe_; uint32_t id_; }; int main () { managed_shared_memory *test_shmseg; data_store *ds; try { test_shmseg = new managed_shared_memory(open_or_create, "seg2", 2048); } catch (std::exception ex) { std::cerr << ex.what() << ' '; } assert(test_shmseg != NULL); try { std::cout << "Free size " << test_shmseg->get_free_memory() << std::endl; std::pair<data_store *, std::size_t> dsdir = test_shmseg->find<data_store>("Datastore"); if (dsdir.first == NULL) { // instantiate a data store std::cout << "Instantiating data store" << std::endl; ds = test_shmseg->construct<data_store>("DataStore")(1, std::string("ds").c_str(), true); if (ds == NULL) { std::cout << "Failed to construct Datastore" << std::endl; exit(1); } } else { std::cout << "Datastore found" << std::endl; ds = dsdir.first; } std::cout << "Data store id " << ds->id() << std::endl; std::cout << "Data store name " << ds->name() << std::endl; } catch (boost::interprocess::bad_alloc &ex) { std::cerr << ex.what() << ' '; } while (1); // wait for the other instance of this program to find the created segment and dump contents } 我无法弄清楚为什么第二个实例能够打开共享内存段但总是卡在互斥锁上 (gdb) bt #0 0x00007ffff7bcd42d in __lll_lock_wait () from /lib64/libpthread.so.0 #1 0x00007ffff7bc8de6 in _L_lock_870 () from /lib64/libpthread.so.0 #2 0x00007ffff7bc8cdf in pthread_mutex_lock () from /lib64/libpthread.so.0 #3 0x0000000000403d6d in boost::interprocess::ipcdetail::posix_recursive_mutex::lock (this=0x7ffff7ff8070) at /usr/include/boost/interprocess/sync/posix/recursive_mutex.hpp:90 #4 0x0000000000403e52 in boost::interprocess::interprocess_recursive_mutex::lock (this=0x7ffff7ff8070) at /usr/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp:163 #5 0x0000000000408457 in boost::interprocess::scoped_lock<boost::interprocess::interprocess_recursive_mutex>::lock (this=0x7fffffffdf30) at /usr/include/boost/interprocess/sync/scoped_lock.hpp:284 #6 0x00000000004073b0 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_get_lock (this=0x7ffff7ff8010, use_lock=true) at /usr/include/boost/interprocess/segment_manager.hpp:1315 #7 0x00000000004069ea in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_generic_find<char> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", index=..., table=..., length=@0x7fffffffe098: 0, is_intrusive=..., use_lock=true) at /usr/include/boost/interprocess/segment_manager.hpp:844 #8 0x0000000000405f1e in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_find_impl<data_store> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", lock=true) at /usr/include/boost/interprocess/segment_manager.hpp:724 #9 0x0000000000405309 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::find<data_store> (this=0x7ffff7ff8010, name=...) at /usr/include/boost/interprocess/segment_manager.hpp:434 #10 0x00000000004044ea in boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul>::find<data_store> (this=0x63ec20, name=...) at /usr/include/boost/interprocess/detail/managed_memory_impl.hpp:346 #11 0x00000000004040f7 in boost::interprocess::basic_managed_shared_memory<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::int---Type <return> to continue, or q <return> to quit--- erprocess::iset_index>::find<data_store> (this=0x63ec20, name=...) at /usr/include/boost/interprocess/managed_shared_memory.hpp:212

任何帮助表示赞赏。

答案
  • 永远等待(不确定是否需要这个,只是添加它以确保linux一旦程序退出就不会释放共享内存)

不,这不是必需的。共享内存是共享的。它保持不变,除非你明确remove()它。

评论

您至少有一个不一致:对象的名称是"Datastore""DataStore" - 确保您匹配拼写。

除此之外,我想

  • 你可能不想要“数组式”分配,你(无意中?)使用
  • 你可能最好使用find_or_construct,它确实消除了潜在的竞争条件(分别在查找和创建新实例之间的检查时间与使用时间窗口)。

除此之外,我没有看到任何直接原因。也许你可以尝试一次,手动删除共享对象,并使用以下简化程序重新测试:

#include <boost/interprocess/managed_shared_memory.hpp>
#include <iostream>
#include <cassert>
namespace bip = boost::interprocess;

class data_store {
  public:
    data_store(uint32_t id, const char *name, bool safe) :
        id_(id), safe_(safe)
    {
        id_ = id;
        assert(name && strlen(name) < (sizeof(name_)-1));
        strncpy(name_, name, sizeof(name_));
        safe_ = safe;
    }

    uint32_t   id()    const { return id_; }
    const char *name() const { return name_; }

  private:
    char name_[32] = {0};
    uint32_t id_;
    bool safe_;
};

int main () try {
    bip::managed_shared_memory seg(bip::open_or_create, "seg2", 2048);
    data_store ds = *seg.find_or_construct<data_store>("DataStore")(1, "ds", true);
    std::cout << "Free size " << seg.get_free_memory() << std::endl;    
    std::cout << "Data store name " << ds.name() << std::endl;
} catch (std::exception ex) {
    std::cerr << ex.what() << '
';
}

它包含一些样式修复以及名称长度上的额外断言。

Live On Coliru

注意:在使用managed_mapped_file的Coliru上,因为在Coliru上没有manged_shared_memory

打印:

Free size 1712
Data store name ds
-rw-r--r-- 1 2001 2000 2.0K Mar  5 12:26 seg2
Free size 1712
Data store name ds

以上是关于提升managed_shared_memory find()方法永远停留在互斥锁上的主要内容,如果未能解决你的问题,请参考以下文章

提升进程间共享内存删除对象而不破坏

boost::interprocess::managed_shared_memory() open_only 在 XP 上失败

如何从 boost::interprocess::managed_shared_memory 对象中获取 shmid

在 Boost Interprocess managed_shared_memory 中搜索时,线程陷入互斥等待

managed_shared_memory 与 windows_shared_memory

如何在程序崩溃后释放 managed_shared_memory:在调试期间使用哪些有效技术?