我已经在这里工作了几天(甚至是posted在推特论坛上)并且能够让第二个进程识别锁定的互斥锁似乎不起作用。请帮忙。这是代码:
一个常见的头文件: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写完共享内存为止?
答案 0 :(得分:4)
好的,这是您的代码存在的一些问题。
SharedMutex
存储在不同的内存区域中,该区域未映射到第二个程序中。
映射区域可以具有不同的基址,因此原始指针在此环境中不起作用。请改用boost::interprocess::offset_ptr
。但请注意,这些指针用于指向同一内存段的指针,因此将SharedMutex和SharedObject放在同一段中是有意义的(或者不是所有这些,使用named_mutex
)。
在main1中,在修改成员变量temp
之前,将sharedMutex
复制到共享内存。您应该确保在共享内存中指针(offset_ptr
- to-be)实际上是有效的。
当您尝试使用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 */
计划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
和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
答案 1 :(得分:0)
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;
}