当主进程使用 fork 创建进程时,我正在制作一个基本程序,该进程从列表中获取第一个元素并打印它。我使用 boost 库来管理共享内存,但这是我第一次使用此类工具,我可能做错了。
#include <iostream>
#include <list>
#include <unistd.h>
#include <sys/wait.h>
#include <vector>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
using namespace std;
using namespace boost::interprocess;
struct shared_data{
interprocess_mutex mtx;
list<int> qqueue;
};
void modify_list(shared_data*& sdat);
int main(){
shared_memory_object shm(open_or_create, "shm", read_write);
shm.truncate(sizeof(shared_data));
mapped_region reg(shm, read_write);
void* address=reg.get_address();
shared_data* shptr=new (address) shared_data;
vector<pid_t> processors;
size_t num_processors=4;
for(int j=1; j<8; ++j){
shptr->qqueue.push_back(j);
}
for(size_t i=0; i<num_processors; ++i){
pid_t pid=fork();
if(pid==0){
modify_list(shptr);
}
else if(pid>0){
processors.push_back(pid);
}
}
for (pid_t cpu : processors) {
int status;
waitpid(cpu, &status, 0);
}
}
void modify_list(shared_data*& sdat){
while(true){
sdat->mtx.lock();
if(sdat->qqueue.empty()){
sdat->mtx.unlock();
break;
}
int ff = sdat->qqueue.front();
sdat->qqueue.pop_front();
sdat->mtx.unlock();
cout<<"Process: "<<getpid()<<" dequeued "<<ff<<"\n";
cout.flush();
}
}
我得到以下输出:
Process: 320 dequeued 1
Process: 320 dequeued 2
Process: 320 dequeued 3
Process: 320 dequeued 4
Process: 320 dequeued 5
Process: 320 dequeued 6
Process: 320 dequeued 7
Process: 321 dequeued 2
既然 2 已经被进程 320 出列,为什么它又被 321 出列,而 2 在列表中只存在一次。
您仍然可以使用我对您之前的问题给出的答案分叉进程 c++ 之间的共享内存。它轻松地展示了如何正确指定分配器,以便您想要的工作正常。
基本上,您需要一个托管细分市场,除非您例如想要滚动自己的分配器(例如,在预分配的内存块上使用 PMR)。另外,请考虑使用固定大小的容器(例如
boost::container::static_vector
)以避免分配。
这是模仿的数据结构:
namespace Shared {
namespace bc = boost::container;
namespace bip = boost::interprocess;
using Segment = bip::managed_shared_memory;
using Manager = Segment::segment_manager;
template <typename T> using Alloc = bc::scoped_allocator_adaptor<bip::allocator<T, Manager>>;
template <typename T> using List = bc::list<T, Alloc<T>>;
struct MyData {
using allocator_type = Alloc<MyData>;
template <typename A> MyData(A&& alloc) : qqueue(std::forward<A>(alloc)) {}
size_t count() const {
for (std::lock_guard lk(mtx);;)
return qqueue.size();
}
void modify_list() {
while (true) {
std::lock_guard lk(mtx);
if (qqueue.empty())
break;
int ff = qqueue.front();
qqueue.pop_front();
std::cout << "Process: " << getpid() << " dequeued " << ff << std::endl;
}
}
void print() const {
std::lock_guard lk(mtx);
fmt::print(" {}\n", qqueue);
}
private:
mutable bip::interprocess_mutex mtx;
List<int> qqueue;
};
} // namespace Shared