2011-02-23 38 views
1

我在Linux 2.6上,我有一個奇怪的問題。我有3個併發進程(從同一進程派生)需要獲得3個不同的共享內存段,每個進程一個進程。每個過程的執行代碼(請注意,「信息」類型是用戶自定義)當進程使用shm_open()時,Linux內核如何分配內存指針?

message *m; 
    int fd = shm_open("message", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 
    ftruncate(fd, sizeof(message)); 
    m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 
    char messagename[16]; 
    snprintf(messagename, sizeof(messagename), "%p", m); 
    char path[32] = "/dev/shm/"; 
    strcat(path, messagename); 
    rename("/dev/shm/message", path); 

讓我解釋一下:我希望每一個進程分配它包含一個消息的共享內存區。爲了確保另一個進程(消息接收者)可以訪問相同的shm,我然後將我的shm文件從「消息」重命名爲以消息指針命名的字符串(這是因爲接收消息的進程已經知道指針)。當我執行程序時,我試圖打印(爲了調試目的)每個進程在使用shm_open獲得的fd映射時收到的指針,並且我注意到它們都獲得了SAME指針。這怎麼可能?我認爲也許其他進程在第一次執行shm_open()後做了重命名,因此我還嘗試通過使用進程共享互斥鎖來使這些代碼行成爲原子操作,但問題仍然存在。

我真的很感激任何形式的幫助或建議。

回答

2

您的進程在分叉時刻都以相同的地址空間佈局開始,然後遵循非常類似的代碼路徑。因此,它們都以相同的價值m結束也就不足爲奇了。

然而,一旦他們成爲獨立的過程,其地址空間成爲獨立的,因此具有相同m所有m S的都指向同一件事並不意味着。

此外,我不確定在創建共享內存塊後重命名/dev/shm條目的想法是安全的還是便攜的。如果你想讓每個進程的共享內存塊有一個唯一的名字,爲什麼不把該名字作爲進程ID(在給定的時間點保證是唯一的)並將其直接傳遞給shm_open,而不是去煩擾之後重命名?

+0

謝謝,您使用pid的想法看起來不錯,我當然會給它一個鏡頭。然而,通過shm_open()我問一個共享的(而不是私有的)內存指針,並且我每次都期待着一個不同的指針,而不管這個進程的虛擬內存空間是什麼,我認爲在共享內存方面並不相關。 此外,即使我爲進程調用的每個shm_open()使用了不同的名稱,它們也都會得到相同的地址。如果shm_open()+ mmap()給出共享內存指針,如果shm的名稱不同,它們又怎麼能相同呢? –

+2

從進程訪問內存的所有訪問都經過該進程的虛擬地址空間。底層內存可能是共享的,但每個應用程序的視圖都是私有的。因此,它可能出現在每個進程中的相同地址,或者不同進程中的不同地址,完全由OS自行決定。 – mhsmith

+1

......或者相反,不同的共享內存塊可能出現在不同進程的相同地址,這就是發生在你身上的事情。 – mhsmith

1

不同進程中的相同虛擬地址可以(通常也會)映射到內存中的不同物理頁面。您可能需要閱讀the wikipedia article on virtual memory

+0

謝謝!我已經知道虛擬內存。不過,我在想,即使進程有不同的內存空間,使用shm_open()和mmap()會返回指向某些共享區域的指針,這些共享區域每次都應該是「唯一」的。 –

0

我解決了類似的問題,只是通過製作mmap之前。所以分叉後,所有進程之間共享相同的區域。然後我將信號量和互斥量放在指定的位置上。它完美的作品。