簡體   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