多进程c ++(11),链表指针作为全局变量

时间:2014-01-11 13:40:11

标签: c++ fork global doubly-linked-list

我遇到的问题是hereherehere以及here

但是,我希望子进程在双向链表的末尾插入一个元素。指向列表的第一个元素是全局的,我想从主进程访问所有列表元素,并且下次使用fork分支main时,我希望能够访问所有元素,并更新它们,并插入更多元素,反过来主要进程再次能够访问修改后的列表。

每个进程都使用execvp进行系统调用(我需要它们能够使用不同数量的参数调用内容)。

我可能会问一个太广泛的问题,但我个人没有比分支和在列表末尾插入元素更进一步。因此,我实际上没有一行代码可以将我带到我想去的地方。我不知道如何在这种情况下使用shm()。

请帮忙。

2 个答案:

答案 0 :(得分:2)

你可以尝试这个..我只是从头开始写它。它是跨平台的,所以总是一个加号。分配器和池可以重复使用。例如,您可以在堆栈上或任何您想要的地方分配任何stl容器..

SharedMemory.hpp:

#ifndef SHAREDMEMORY_HPP_INCLUDED
#define SHAREDMEMORY_HPP_INCLUDED

#if defined _WIN32 || defined _WIN64
    #include <windows.h>
#else
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <dlfcn.h>
    #include <fcntl.h>
    #include <unistd.h>
#endif

#include <string>
#include <cstdint>

class SharedMemory
{
    private:
        std::string name;
        std::size_t size;
        void* data;
        void* hFileMap;

    public:
        SharedMemory(std::string name, std::size_t size) : name(name), size(size), data(nullptr), hFileMap(nullptr) {};
        ~SharedMemory();

        bool Open();
        bool Create();

        std::size_t GetSize() const {return this->size;}
        void* GetPointer() const {return this->data;}
};

#endif // SHAREDMEMORY_HPP_INCLUDED

SharedMemory.cpp:

#include "SharedMemory.hpp"

SharedMemory::~SharedMemory()
{
    if (data)
    {
        #if defined _WIN32 || defined _WIN64
        UnmapViewOfFile(data);
        data = nullptr;

        if (hFileMap)
        {
            if (CloseHandle(hFileMap))
            {
                hFileMap = nullptr;
            }
        }

        #else

        if (data)
        {
            munmap(data, size);
            data = nullptr;
        }

        if (hFileMap)
        {
            if (!close(hFileMap))
            {
                hFileMap = nullptr;
            }
        }
        #endif
    }
}

bool SharedMemory::Open()
{
    #if defined _WIN32 || defined _WIN64
        if ((hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, name.c_str())) == nullptr)
        {
            return false;
        }

        if ((data = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, size)) == nullptr)
        {
            CloseHandle(hFileMap);
            return false;
        }
    #else

        if ((hFileMap = open(MapName.c_str(), O_RDWR | O_CREAT, 438)) == -1)
        {
            return false;
        }

        if ((data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, hFileMap, 0)) == MAP_FAILED)
        {
            close(hFileMap);
            return false;
        }
    #endif
    return true;
}

bool SharedMemory::Create()
{
    #if defined _WIN32 || defined _WIN64
        if ((hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, size, name.c_str())) == nullptr)
        {
            return false;
        }

        if ((data = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, size)) == nullptr)
        {
            CloseHandle(hFileMap);
            return false;
        }

    #else

        if ((hFileMap = open(MapName.c_str(), O_RDWR | O_CREAT, 438)) == -1)
        {
            return false;
        }

        if ((data = mmap(nullptr, Size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, hFileMap, 0)) == MAP_FAILED)
        {
            close(hFileMap);
            return false;
        }
    #endif
    return true;
}

Pools.hpp:

#ifndef POOLS_HPP_INCLUDED
#define POOLS_HPP_INCLUDED

#include <stdexcept>
#include <cstdint>
#include "SharedMemory.hpp"

template<typename T>
class SharedPool
{
    private:
        T* data;
        SharedMemory* shm;
        std::size_t size;

    public:
        SharedPool(SharedMemory* shm) : data(reinterpret_cast<T*>(shm->GetPointer())), shm(shm), size(shm->GetSize()) {};

        template<typename U = T>
        void* allocate(std::size_t n, const void* hint = 0) {return &data[0];}

        template<typename U = T>
        void deallocate(U* ptr, std::size_t n) {}

        template<typename U = T>
        std::size_t max_size() const {return size;}
};

#endif // POOLS_HPP_INCLUDED

main.cpp(从进程1向共享内存添加值):

#include "SharedMemory.hpp"
#include "Allocators.hpp"
#include "Pools.hpp"

#include <vector>
#include <iostream>

int main()
{
    SharedMemory mem = SharedMemory("Local\\Test_Shared_Memory", 1024);
    if (!mem.Open() && !mem.Create())
    {
        throw std::runtime_error("Error Mapping Shared Memory!");
    }

    auto pool = PoolAllocator<int, SharedPool<int>>(SharedPool<int>(&mem));
    std::vector<int, decltype(pool)> v(pool);

    int* ptr = reinterpret_cast<int*>(mem.GetPointer());
    std::cout<<"Pushing 3 values to: "<<ptr<<"\n";

    v.push_back(100);
    v.push_back(200);
    v.push_back(700);

    std::cin.get();
}

main.cpp(从共享内存中读取值的过程2):

#include "SharedMemory.hpp"
#include "Allocators.hpp"
#include "Pools.hpp"

#include <vector>
#include <iostream>

int main()
{
    SharedMemory mem = SharedMemory("Local\\Test_Shared_Memory", 1024);
    if (!mem.Open() && !mem.Create())
    {
        throw std::runtime_error("Error Mapping Shared Memory!");
    }

    auto pool = PoolAllocator<int, SharedPool<int>>(SharedPool<int>(&mem));
    std::vector<int, decltype(pool)> v(pool);

    int* ptr = reinterpret_cast<int*>(mem.GetPointer());
    std::cout<<"Reading 3 values from: "<<ptr<<"\n";

    v.reserve(3);
    std::cout<<v[0]<<"\n";
    std::cout<<v[1]<<"\n";
    std::cout<<v[2]<<"\n";

    std::cin.get();
}

答案 1 :(得分:1)

这是一个棘手的问题。

一种方法是使用Shared Memory,在构建链表时,给它自己的分配器,以使用共享内存。其他方法是根据共享内存实现自己的链表。

你也可以尝试使用boost - Boost interprocess,这可能是理想的解决方案。

具体而言 - interprocess with containers