Linux IPC之POSIX共用記憶體__Linux

來源:互聯網
上載者:User

導言:System V共用記憶體和共用檔案對應,允許無關進程共用記憶體地區以便執行IPC通訊。但這兩種技術都存在一些不足:1. System V共用記憶體模型使用的是鍵和標識符,這與標準的UNIX I/O模型使用檔案名稱和描述符的做法是不一致的,這種差異意味著使用System V共用記憶體段需要一整套全新的系統調用和命令。2. 使用一個共用檔案對應來進行IPC要求建立一個磁碟檔案,即使無需對共用地區進行持久儲存也需要這樣做,除了因需要建立檔案所帶來的不便之外,這種技術還會帶來一些檔案I/O開銷。由於存在這些不足,所以POSIX.1b定義了一組新的共用記憶體API —— POSIX共用記憶體。 概述

POSIX共用記憶體能夠讓無關進程共用一個映射地區,而無需建立一個相應的檔案對應。Linux從核心2.4起開始支援POSIX共用記憶體。SUSv3並沒有對POSIX共用記憶體的實現細節進行規定,特別是沒有要求使用一個(真實或虛擬)檔案系統來標識共用記憶體對象,但是很多UNIX實現都採用了檔案系統來標識共用記憶體對象。一些UNIX實現將共用對象名建立為標準檔案系統上一個特殊位置處的檔案,Linux使用掛載於/dev/shm目錄下的專用tmpfs檔案系統,這個檔案系統具有核心持久性,即它所包含的共用記憶體對象會一直持久,即使當前不存在任何進程開啟它,但這些對象會在系統關閉之後丟失。

注意:系統上POSIX共用記憶體地區佔據的記憶體總量受限於底層的tmpfs檔案系統的大小,這個檔案系統通常會在啟動時使用預設大小(如,256MB)進行掛載,如果有必要的話,root使用者能夠使用命令mount -o remount,size=<num-bytes>重新掛載這個檔案系統來修改它的大小。

要使用POSIX共用記憶體對象,需要完成下列工作: 使用shm_open()函數開啟一個與指定的名字對應的對象,shm_open()函數與open()系統調用類似,它會建立一個新共用對象,或開啟一個既有對象。shm_open()會返回一個引用該對象的檔案描述符。 將上一步中獲得的檔案描述符傳入mmap()調用,並在其flags參數中指定MAP_SHARED,這會將共用記憶體對象映射到進程的虛擬位址空間。與mmap()的其他用法一樣,一旦映射了對象之後就能夠關閉該檔案描述符,而不會影響到這個映射。然後,有可能需要將這個檔案描述符保持在開啟狀態,以便後續的fstat()和ftruncate()調用使用這個檔案描述符。

說明:
1. POSIX共用記憶體上shm_open()和mmap()的關係類似於System V共用記憶體上shmget()和shmat()的關係。使用POSIX共用記憶體對象需要兩步式過程(shm_open()+mmap()),而沒有使用單個函數來執行兩項任務是因為曆史原因。在POSIX委員會增加這個特性時,mmap()調用已經存在了,實際上,這裡所需要做的事情是使用shm_open()調用替換open()調用,其中差別是使用shm_open()無需在一個基於磁碟檔案系統上建立一個檔案。
2. 由於共用記憶體對象的引用是通過檔案描述符來完成的,因此可以直接使用UNIX系統中已經定義好的各種檔案描述符系統調用,而無需增加新的系統調用。 使用共用記憶體對象

#include <fcntl.h>      // Defines 0_* constants#include <sys/stat.h>   // Defines mode constants#include <sys/mman.h>   // returns file descriptor on success, or -1 on errorint shm_open(const char *name, int oflag, mode_t mode);
name參數標識出了待建立或待開啟的共用記憶體對象。 oflag參數是一個改變調用行為的位元遮罩。如果oflag中不包含O_CREAT,那麼就開啟一個既有對象,如果指定了O_CREAT,那麼在對象不存在時就建立對象。同時指定O_EXCL和O_CREAT能夠確保調用者是對象的建立者,如果對象已經存在,就返回一個EEXIST錯誤。oflag參數還表明了調用進程在共用記憶體對象上的訪問模式,其取值為O_RDONLY或O_RDWR。而O_TRUNC會導致在成功開啟一個既有共用記憶體對象之後將對象的長度截斷為0。
oflag 作用
O_CREAT 對象不存在的時候建立
O_EXCL 與O_CREATE互斥地建立對象
O_RDONLY 開啟唯讀訪問
O_RDWR 開啟讀寫訪問
O_TRUNC 將對象長度截斷為0
mode參數能取的位值與檔案上的許可權位值是一樣的,與open()系統調用一樣,mode中的許可權掩碼將會根據進程umask來取值,與open()不同的是,在調用shm_open()時總是需要mode參數,在不建立新對象時需要將這個參數指定為0。

一個新共用記憶體對象被建立時,其初始長度會被設定為0,這意味著在建立完一個新共用記憶體對象之後,通常在調用mmap()之前需要調用ftruncate()來設定對象的大小。在調用完mmap()之後可能還需要使用ftruncate()來根據需求擴大或收縮共用記憶體對象。在擴充一個共用記憶體對象時,新增加的位元組會自動被初始化為0。

SUSv3要求POSIX共用記憶體對象至少具備核心持久性,即它們會持續存在直到被顯示刪除或系統重啟。當不再需要一個共用記憶體對象時,就應該使用shm_unlink()刪除它。

#include <sys/mman.h>// returns 0 on success, or -1 on errorint shm_unlink(const char *name);

shm_unlink()函數會刪除通過name指定的共用記憶體對象。刪除一個共用記憶體對象不會影響對象的既有映射,它會保持有效直到相應的進程調用munmap()或終止,但會阻止後續的shm_open()調用開啟這個對象。一旦所有進程都解除映射這個對象,對象就會被刪除,其中的內容會丟失。 例子

https://github.com/gerryyang/TLPI/tree/master/src/pshm 共用記憶體API比較

TODO

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.