2014-01-11 63 views
2

我有經典的問題給出hereherehere,也here多進程C++(11)鏈表指針作爲全局變量

不過,我想一個子進程結束時插入元素的雙向鏈表。指向列表的第一個元素是全局的,我想訪問主進程中的所有列表元素,並且下一次我使用fork來分支main,我想要abe來訪問所有元素,並更新他們,並插入更多的元素,反過來主進程再次能夠訪問修改列表。

每個進程都會通過系統調用execvp退出(我需要他們能夠使用不同數量的參數調用內容)。

我或許在問一個太寬泛的問題,但我個人沒有得到比分支和在列表末尾插入元素更多的東西。因此,我實際上沒有一行代碼將我帶到了我想去的地方。我不知道如何在這種情況下使用shm()。

請幫忙。

+0

線程將共享地址空間,所以他們沒有必要SHM的()(確保你知道,如果你是創建一個新的進程或線程),其餘的依賴於你的確切位置 - 它們是讀取還是寫入,還是兩者都有?等 – user3125280

+1

使用共享內存不一定就夠了 - 特別是如果shm中的指針指向不共享的內存。這聽起來像你不應該使用進程 - 相反,你應該在同一個進程中使用線程(pthreads,或任何你的環境支持)。其中一個原因是共享全局空間只有在發生寫入時才共享......然後它是兩個獨立的內存緩衝區。 – mah

+0

我使用fork來分支攜帶使用的輸入,然後根據這些輸入更新全局變量,然後啓動外部過程,然後終止子進程,這樣在下一個用戶輸入來臨之前,主進程知道到底是什麼在最後一次通話中繼續。我意識到,殘酷的分析將是在分叉之前進行更新,或者由於用戶輸入也被複制,讓孩子只調用外部程序,而主要更新變量。但是,我真的可以在孩子身上進行更新,而不是採用殘酷的解決方案嗎? – Sean

回答

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中(來自過程中的一個添加值以共享存儲器):

#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中(共享內存的過程中有兩個讀數值):

#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(); 
} 
+0

成功,這工作,謝謝你,但我可能會在晚些時候問更多的問題.. – Sean

+0

我不介意。詢問。我不會評論我的代碼很多,所以我希望你能理解它。如果沒有,請隨時問任何你喜歡的東西。我自己或其他人(誰看到它)會有所幫助。現在是 – Brandon

+0

,是的,我確實看到它是如何工作的。但你必須記住,我是一個具有數學背景的氣象工程師(試圖自動化我的天氣相關的東西 - 自己做比自己更容易,而不是爲了可用性而解釋究竟需要什麼) - 可能是我知道這是錯的情況。讓我們來看看 。 – Sean

1

這是一個棘手的問題。

一種方法是使用Shared Memory,並且當您構建鏈表時,給它一個自己的分配器,以使用共享內存。其他方法是基於共享內存實現您自己的鏈接列表。

您也可以嘗試使用boost - Boost interprocess,這可能是理想的解決方案。

具體來說 - interprocess with containers

+0

OP聲明_我不知道如何在這個場景中使用shm(),所以簡單地建議他使用共享內存似乎不夠。 – mah