2009-12-23 46 views
8

我們需要多個程序來調用公共庫中的函數。庫函數訪問並更新一個通用的全局內存。每個程序的函數調用都需要看到這個通用的全局內存。這是一個函數調用需要查看任何以前的函數調用的更新,即使從另一個程序調用。 出於兼容性的原因,我們對如何共享庫暴露出的功能必須操作多個設計約束:實例化共享內存中的對象C++

  • 被全局聲明的任何數據項(包括標準數據類型和對象)必須對所有主叫方可見不管代碼正在運行的線程。
  • 在函數中本地聲明的任何數據項只在該函數內可見。
  • 任何標準數據類型或任何類的實例可能出現在本地或全局或兩者。

一個解決方案是將庫的通用全局內存放在命名共享內存中。第一個庫調用將創建指定的共享內存並對其進行初始化。隨後的程序調用將獲得共享內存的地址,並將其用作指向全局數據結構的指針。全局聲明的對象實例需要在共享內存中動態分配,而本地聲明的對象實例可以放在堆棧中或調用者線程的本地堆中。出現問題是因爲全局內存中的初始化對象可以創建並指向分配(新)附加內存的子對象。這些新分配也需要在共享內存中,並由所有庫呼叫者看到。另一個複雜因素是這些對象包含字符串,文件等,也可以用在調用程序中。在調用程序中聲明時,對象的內存對於調用程序是本地的,不是共享的。所以對象的代碼需要處理這兩種情況。 在我們看來,解決方案將要求我們重寫全局佈局新的常規新操作符和刪除操作符。我們找到了一個內存管理系統的設計,看起來可以工作,但我們還沒有找到任何實際的實現。如果有人知道Nathan Myers的內存管理設計(http://www.cantrip.org/wave12.html?seenIEPage=1)的實現,我會很感激鏈接。或者,如果有人知道另一個可以動態分配對象的共享內存管理器,我也很想知道它。我檢查了Boost庫和我能找到的所有其他來源,但似乎沒有做我們需要的東西。我們寧願不必自己寫一個。由於性能和健壯性非常重要,因此使用經過驗證的代碼會很好。提前感謝任何想法/幫助。

感謝您對ATL和OSSP庫的建議。我現在正在檢查它們,但是如果目標是Unix,恐怕ATL太溫和了。

另一件事現在看起來很清楚。由於可以在執行過程中動態創建對象,因此內存管理方案必須能夠分配額外的共享內存頁面。現在開始看起來像一個全面的堆更換內存管理器。

+2

是不是創建服務器的問題的標準解決方案,哪些客戶端應用程序可以使用?共享內存比共享內存要容易得多,這不太可能因爲你給的原因而工作。 – 2009-12-23 15:50:16

+0

同意尼爾。 – wheaties 2009-12-23 15:54:16

+0

是的。重新設計應用程序將是解決問題的最簡單方法。不幸的是,由於與其他組件相關的設計限制,我們沒有這個選項。 – BillC 2009-12-23 23:04:37

回答

0

OSSP毫米 - 共享內存分配:

人3毫米

1
+1

正如我在帖子中提到的那樣,我們查看了Boost庫。不幸的是,它沒有完成我們所需要的。不過,它引導我們獲得了一些有希望的資源,例如我在帖子中提到的鏈接。 – BillC 2009-12-23 23:09:39

0

正如我相信你已經發現,這是一個非常複雜的問題,很難正確實施。從我的經驗中得到一些提示。首先,你一定要使用信號量來同步對共享內存分配的訪問。其次,多進程對共享對象的修改也需要通過信號量來保護。最後,在定義對象和數據結構時,您需要考慮共享內存區域開始時的偏移量而不是絕對指針值(通常可以將內存映射到每個附加進程中的不同地址,儘管你可以選擇一個固定的映射地址,如果你需要)。把它放在一起是一個很難的部分。如果一個進程意外停止,基於共享內存的數據結構很容易被破壞,所以通常需要一些清理/恢復機制。

+0

你完全正確。問題很複雜,這就是爲什麼我們不想從頭開始編寫代碼。 – BillC 2009-12-23 23:08:05

0

還研究互斥和信號量。當兩個或兩個以上的實體需要共享內存或數據時,需要有一個「交通信號」機制來限制只有一個用戶的寫訪問。

+0

謝謝。我們知道這需要線程安全,並已實施互斥來控制訪問。我們所面臨的主要問題是如何確保某些對象以及它們實例化的任何對象在共享內存中分配,而同一對象的其他實例則在本地分配。 – BillC 2009-12-23 23:06:57

+0

混合過程 - 像你所描述的本地和共享內存似乎通常就像是一場災難。定義更正式的進程間通信協議可能是更好的方法。 – 2009-12-27 01:16:16