2010-01-25 109 views
1

我們的應用程序依賴於外部,第三方提供的配置(包括自定義驅動/決策功能),可加載的.so文件。如何在共享內存中得到共享對象

獨立地,它使用共享存儲器,其中幾乎所有的揮發性狀態被保持的組塊的外部CGI模塊,從而使外部模塊可以讀取它並修改它適用配合。

問題是CGI模塊還需要很多來自.so的永久配置數據,而主應用程序在兩個存儲區之間執行了大量完全不必要的複製操作以使數據可用。這個想法是讓整個共享對象加載到共享內存中,並使其直接可用於CGI。問題是:如何?

  • dlopen和dlsym不提供任何設備來指定加載SO文件的位置。
  • 我們試過shmat()。它似乎只在某些外部CGI實際嘗試訪問共享內存之前起作用。然後,指向的區域就像私密,就好像它從未共享一樣。也許我們做錯了什麼?
  • 在需要它的每個腳本中加載.so都是沒有問題的。結構的龐大規模與呼叫頻率相關(某些腳本每秒調用一次以生成實時更新),而這是一個嵌入式應用程序,它使其不起作用。
  • memcpy()將.so放入shm中也不好 - 某些結構和所有函數通過指針相互關聯。

回答

2

我想最簡單的選項是使用內存映射文件,什麼尼爾提出了。如果這個選項填不好,另一種方法是可以定義專用的分配器。這裏有一個關於它的好文章:Creating STL Containers in Shared Memory

還有優秀的IonGaztañaga的Boost.Interprocess庫與shared_memory_object和相關功能。Ion已經向未來TR的C++標準化委員會提出瞭解決方案:Memory Mapped Files And Shared Memory For C++ 可能表明這是值得考慮的解決方案。

+0

雖然它不直接回答我的問題,但我猜這是最接近它。我還沒有看到一個有用的調用shmat()與第二個參數不同於NULL。 – 2010-01-31 00:01:43

+0

將它留空,並讓系統決定正在存儲的內存段的位置,並將其地址返回給您。 – mloskot 2010-01-31 00:18:57

2

將實際的C++對象放在共享內存中非常非常非常困難,就像您發現的那樣。我強烈建議你不要這麼做 - 將需要在共享內存或內存映射文件中共享的數據更加簡單並且可能更加健壯。

3

使用共享內存時要記住的第一件事是,相同的物理存儲器很可能被映射到兩個進程的虛擬地址空間爲不同的地址。這意味着如果指針在數據結構中的任何地方使用,它們將會導致問題。一切都必須通過索引或偏移才能正常工作。要使用共享內存,您必須清除代碼中的所有指針。

當加載一個.so文件,只有一個.so文件代碼的副本被加載(因此稱爲共享對象)。

fork也可以在這裏你的朋友。大多數現代操作系統都實現了寫時複製語義。這意味着當您的數據段寫入到給定的數據段時,您的數據段只會被複制到單獨的物理內存中。

0

您需要實現對象的Serialization 序列化函數會將您的對象轉換爲字節,然後您可以在SharedMemory中寫入字節並讓您的CGI模塊將字節反序列化回對象。

+0

恐怕我無法序列化C函數。 – 2012-02-10 12:49:23