繁体   English   中英

Boost进程间互斥体崩溃而不是等待锁定?

[英]Boost interprocess mutex crashes instead of waiting on a lock?

我已经呆了好几天(甚至发布在boost论坛上),并且能够使第二个进程识别出锁定的互斥体似乎不起作用。 请帮忙。 这是代码:

通用头文件: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完成对共享内存的写入?

好的,这是您代码的一些问题。

  1. SharedMutex存储在另一个存储区中,该存储区未在第二个程序中映射。

  2. 映射的区域可以具有不同的基地址,因此原始指针在此环境中将不起作用。 请使用boost::interprocess::offset_ptr 但是请注意,这些操作适用于指向同一内存段的指针,因此将您的SharedMutex和SharedObject放在同一段中是有意义的(或者代替所有这些,请使用named_mutex )。

  3. 在main1中,您修改成员变量sharedMutex 之前temp复制到共享内存。 您应该确保在共享内存中指针( offset_ptr -to-be)实际上是有效的。

  4. 当你试图用锁scoped_lock使用lockWithWriteLock功能,锁在函数的出口立即解锁。 因此,一旦解决了上述所有问题,并且摆脱了崩溃,您仍然将无法获得预期的输出-应该更改代码的逻辑。

和代码:

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 */

PROGRAM1:

#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

和Program2:

#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

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM