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

Nav*_*Nav 0 c++ boost boost-interprocess boost-mutex

我已经在这里待了好几天(甚至发布在 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 */ 
Run Code Online (Sandbox Code Playgroud)

这是第一个程序:

#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
Run Code Online (Sandbox Code Playgroud)

这是第二个程序:

#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 
Run Code Online (Sandbox Code Playgroud)

程序 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)
Run Code Online (Sandbox Code Playgroud)

我首先运行 program1,它锁定互斥锁并保持锁定 60 秒。在那段时间里,我运行程序 2 以查看它是否等待锁定,但它崩溃了。如何让程序 2 等待互斥锁直到程序 1 完成写入共享内存?

Ros*_*lav 6

好的,您的代码存在一些问题。

  1. SharedMutex被存储在不同的存储器区域,该区域未在第二程序进行映射。

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

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

  4. 当您尝试scoped_lock使用您的lockWithWriteLock功能锁定时,该锁定会在该功能退出时立即解锁。因此,一旦您修复了上述所有问题并摆脱了崩溃,您仍然不会获得预期的输出 - 应该更改代码的逻辑。

和代码:

共享对象文件

#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 */
Run Code Online (Sandbox Code Playgroud)

程序1:

#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
Run Code Online (Sandbox Code Playgroud)

和程序2:

#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
Run Code Online (Sandbox Code Playgroud)