2011-02-14 240 views
17

我在Linux 2.6中。我有一個環境,其中2個進程通過消息傳遞模式的簡單實現來模擬(使用共享內存)數據交換。通過使用mmap在進程之間共享內存

我有一個客戶端進程(從父,這是服務器分叉),其與寫入一個結構(消息),以創建的存儲器映射區域(後叉):

message *m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)

這然後將指針寫入隊列(以鏈表的形式)到另一個共享內存區域,該區域對於服務器和客戶端進程是通用的(因爲如果在fork之前創建了相同的代碼)。然後服務器讀取該區域,獲取消息指針並對其進行處理。

的問題是,* m是fork()和當所述服務器進程試圖訪問被指向的存儲器位置,得到了一個分割錯誤之後創建的。在客戶端創建它之後,是否可以將該內存區域附加到服務器POST分叉?

注意:我不希望在分叉之前將指針指向消息(然後再與服務器共享),因爲我通常不知道客戶端要發送給服務器的消息數量,以及可能有超過1個客戶端進程,所以我只想在客戶端需要發送消息時創建一個新的共享內存塊,並在服務器收到該消息後取消映射。

注意:這是爲學術目的:我知道這是不是解決這個問題的最好辦法,但我只需要按照這條道路。

在此先感謝!

回答

25

在客戶端創建它之後,是否可以將該內存區域附加到服務器POST分叉?

MAP_ANONYMOUS|MAP_SHARED映射的內存只能被mmap()調用的進程或其子進程訪問。另一個進程無法映射相同的內存,因爲該內存不能從其他地方引用,因爲它是匿名

使用shm_open()調用有可能創建名爲共享內存,可以通過不相關的進程來引用和映射共享內存。

+0

謝謝!我用`shm_open()`然後用`mmap()`給出了fd,它部分地解決了這個問題。在fd是mmap之後,是否可以重命名(使用rename()`)我提供給`shm_open()`的「tag」字符串?我試過這樣做,但後來,當我嘗試從另一個使用重命名標記的進程使用`shm_open()`時,我得到一個運行時「總線錯誤」。 注意:我注意到在/ sys/shm /重命名文件存在,所以重命名似乎成功。 – 2011-02-14 16:25:12

6

這不起作用。

如果叉()之後創建一個映射,它不會在其他相關過程(ES)是相同的。

你不能假設指針以這種方式共享。如果你真的想這樣做(我不推薦它!),你應該在fork()之前mmap一個大的區域,然後以某種方式分配合適大小的緩衝區(沒有與其他進程的競爭條件當然!)並傳遞這些指針。

在fork之後調用mmap()的兩個相關進程可能會得到相同的指針,指向不同的內存。事實上,這很可能。

1

僅供任何人在2018年及以後閱讀此問題。 解決方案現在使用memfd_create創建匿名文件並使用unix套接字將此文件句柄傳遞給其他進程。

memfd_create是一個只有linux的系統調用