2015-10-18 62 views
0

我已经在这里待了好几天(即使在升压论坛上也是posted),并且能够让第二个进程识别锁定的互斥锁,但这似乎不起作用。请帮忙。这是代码: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) 

我第一次运行程序1,其锁定互斥锁,并保持它锁定为60秒。在那段时间里,我运行程序2来查看它是否在锁上等待,但它崩溃。如何让程序2等待互斥量,直到程序1写完共享内存为止?

+0

ERM “这个帖子没有被邮件列表接受呢。” - 所以看起来你并没有在boost邮件列表中发布任何内容。你必须先成为会员。 – sehe

回答

4

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

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

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

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

  4. 当您尝试使用lockWithWriteLock函数与scoped_lock锁定时,该函数在函数退出时立即解锁。所以一旦你解决了上述所有问题,并且你摆脱了崩溃,你仍然不会得到预期的输出 - 你的代码的逻辑应该改变。

和代码:

共享对象。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 
+0

非常感谢罗斯蒂斯拉夫。我也尝试过'named_mutex',但它没有奏效。也许我错误地实现了它。实际的代码示例在这里会有所帮助,因为我已经尝试了很多东西并且引用了boost示例代码,但锁定不起作用。这是我在这里发布的最后一招。你有可能用工作代码更新你的答案吗?我相信它会帮助更多的程序员。 – Nav

+0

@Nav这是工作代码。与你的差异,看看不同之处。 'offset_ptr'不在那里使用,但我认为你会明白。 [main1](http://pastebin.com/ANMLnT5P)[main2](http://pastebin.com/HGyxNstr)[main.h](http://pastebin.com/nfGpePmJ) – Rostislav

+0

谢谢@Rostislav。非常感激。我已将代码添加到您的答案中。我还必须添加一些异常处理,因为如果程序运行有点不正常,它往往会崩溃,因为它找不到共享内存或进程异常,说它无法找到文件或目录。我会处理的。您在帮助解决如何解决锁定问题上有很大的帮助。 – Nav

0

罗斯季斯拉夫曾使用名为互斥建议,所以只是把一个名为互斥的例子太(尽管我曾经想要读写器锁,并且这些锁似乎不支持na med mutexes ...我可能是错误的)。

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