C++ 在分叉进程之间共享内存(我做错了什么)

问题描述 投票:0回答:1

当主进程使用 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++ boost shared-memory interprocess
1个回答
0
投票

您仍然可以使用我对您之前的问题给出的答案分叉进程 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
© www.soinside.com 2019 - 2024. All rights reserved.