2015-10-18 66 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; 
}