2017-10-19 104 views
0

我承認,這是一個只是沒有點擊我的主題的作業,所以更多的解釋集中回答將不勝感激。無法將我的共享內存的名稱寫入管道

我想爲我的多個其他進程創建共享內存,以便能夠訪問給定共享內存的名稱。我的其他進程通過管道連接到父進程,我想在共享內存的名稱創建後寫入管道。這是我的代碼到目前爲止。我從來沒有能夠做到這一點。

當我寫出註釋時,該程序將工作一次。但是,當我嘗試再次運行該程序時,我需要更改名稱空間的名稱以使其正常工作。我不明白爲什麼會這樣。我確定有一個我不明白的功能之一。

int shm; 
    char *p; 
    shm = shm_open("Name", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 
    size_t len = 4 * 255; 

    if (ftruncate(shm, len) == -1) { 
    perror("Truncate"); 
    return 1; 
    } 

    p = mmap(0, 4, PROT_WRITE, MAP_SHARED, shm, 0); 
    if (p == MAP_FAILED){ 
    perror("mmap"); 
    return 1; 
    } 

    write(fd[1], "Name", 30); 

    printf("Initiator: Shared memory for Consonanats is %d.\n", shm); 
+0

任何打開的資源在完成後都應該關閉。你應該'shm_close'你的共享內存。每次重新運行程序時,這可能會擺脫改變命名空間的需要。 – Hypino

+0

共享內存段的名稱應該以斜槓('/')開頭。 –

+0

@Hypino,你好像拼錯了「'shm_unlink'」。沒有'shm_close()',至少不是'shm_open()'的標準對應物。 –

回答

0

write()調用的參數不一致:

write(fd[1], "Name", 30); 

您正在嘗試寫30個字節的5字節數組,這顯然超支數組邊界的。

此外,您沒有檢查您的write()呼叫的返回值。原則上,可能會發生短暫寫入,因此您需要進行一次或多次其他調用來傳輸其餘字節。也許更可能的是,寫作可能會完全失敗,在這種情況下,您可能想要注意並做一些事情。任何一種情況都會通過write()的返回值發出信號。

此外,你寫的:

當我嘗試再次運行該程序,我需要改變我的 名字空間的名字爲它工作。我不明白爲什麼會這樣。 我確信有這些功能之一的屬性我不知道 。

是的,肯定有一個屬性你不明白:共享內存段有內核範圍和持久性。除此之外,這意味着他們的一生不限於創造他們的過程,而且他們的名字對系統而言是全球性的。這就是爲什麼不同的進程可以通過指定相同的名稱來獲得對同一段的訪問。

正如@Hypino在評論中所看到的,您永遠不會刪除您創建的細分受衆羣。事實上,你不能直接這樣做;相反,您必須通過shm_unlink()取消的鏈接。這將段的名稱與內核分離,但不直接銷燬它。這是不安全的,因爲其他進程(甚至是同一進程)可能仍然在使用它。在被解除鏈接之後,該細分市場將準備好拆除和移除,但這隻會在沒有更多流程映射時纔會發生。同時,可以創建具有給定名稱的不同分段。

因此,通常的做法是在共享內存段安全實用時儘快斷開鏈接。實際上,這意味着在需要映射它的所有進程(通過名稱)之後,儘快完成此操作。段映射是每個進程的屬性,所以它們在進程退出時消失。

但實際上,目前尚不清楚爲什麼重複使用名稱會導致麻煩。除非在標誌中指定了O_EXCL,否則應該能夠打開先前運行中剩餘的現有共享內存段。我懷疑這個特定的問題涉及到你省略的代碼。

另外,關於細分名稱,請注意您命名選擇的自由並不是絕對的。作爲Linux手冊shm_open()所說:

對於便攜式應用,共享存儲器對象應由形式/somename的 名稱來識別;即由最初的 斜線組成的最多爲NAME_MAX(即255個)字符的以NULL結尾的字符串,後跟一個或多個字符,其中沒有一個是斜槓。

+0

你比我的教授在整個演講中多教了我三段,非常感謝!不勝感激。 – user4493284