效率: 採用共享內存通訊的一個顯而易見的好處是效率高,由於進程能夠直接讀寫內存,而不須要任何數據的拷貝。對於像管道和消息隊列等通訊方式,則須要在內核和用戶空間進行四次的數據拷貝,而共享內存則只拷貝兩次數據[1]: 一次從輸入文件到共享內存區,另外一次從共享內存區到輸出文件。實際上,進程之間在共享內存時,並不老是讀寫少許數據後就解除映射,有新的通訊時,再從新建 立共享內存區域。而是保持共享區域,直到通訊完畢爲止,這樣,數據內容一直保存在共享內存中,並無寫回文件。共享內存中的內容每每是在解除映射時才寫回 文件的。所以,採用共享內存的通訊方式效率是很是高的。函數
共享內存沒有任何的同步與互斥機制,因此要使用信號量來實現對共享內存的存取的同步ui
shmget函數spa
shmget函數建立一個新的共享內存區,或者訪問一個已存在的共享內存區。操作系統
#include <sys/shm.h>.net
int shmget (key_t key, size_t size, int oflag) ;unix
返回值是一個稱爲共享內存區標識符的整數,其餘三個shmXXX函數就用它來指代這個內存區。指針
參數key既能夠是ftok的返回值,也能夠是IPC_PRIVATE。系統創建IPC通信 ( 消息隊列、 信號量和 共享內存) 時必須指定一個ID值。一般狀況下,該id值經過ftok函數獲得,由內核變成標識符,要想讓兩個進程看到同一個信號集,只需設置key值不變就能夠。blog
參數size是指定內存區的大小。(若訪問已存在的內存區,則size應爲0),它的值通常爲一頁大小的整數倍(未到一頁,操做系統向上對齊到一頁,可是用戶實際能使用只有本身所申請的大小)。隊列
參數oflag是讀寫權限值的組合。建立一個新的共享內存,將shmflg 設置了IPC_CREAT標誌後,共享內存存在就打開。而IPC_CREAT | IPC_EXCL則能夠建立一個新的,惟一的共享內存,若是共享內存已存在,返回一個錯誤。通常咱們會還或(‘|’)上一個文件權限進程
當實際操做爲建立一個新的共享內存區時,該內存區被初始化爲size字節的0。
shmat函數
由shmget函數建立或打開一個共享內存區後,經過調用shmat把它附接到調用進程的地址空間。
#include <sys/shm.h>
void* shmat (int shmid, const void* shmaddr, int flag) ;
參數shmid是由shmget返回的標識符。
shmat的返回值是所指定的共享內存區在調用進程內的起始地址。(通常把參數shmaddr置爲NULL,讓系統替調用者選擇地址)
參數flag能夠指定SHM_RDONLY值,它限定只讀訪問。(默承認同時讀寫)一般爲0.
shmdt函數
當一個進程完成某個共享內存區的使用時,它能夠調用shmdt斷接這個內存區。
#include <sys/shm.h>
int shmdt (const void* shmaddr) ;
參數addr是之前調用shmat時的返回值
當一個進程終止時,它當前附接着的全部共享內存區都自動斷接掉。
注意,本函數只是斷開關聯,並不刪除所指定的共享內存區。刪除工做經過以IPC_RMID命令調用shmctl完成。(XSI IPC都是隨內核持續的)
shmctl函數
shmctl提供了對一個共享內存區的多種操做。
#include <sys/shm.h>
int shmctl (int shmid, int cmd, struct shmid_ds* buff) ;
參數cmd:
IPC_RMID 從系統中刪除該共享存儲段。由於每一個共享存儲段有一個鏈接計數器,因此除非使用該段的最後一個進程終止或與該段脫接,不然不會實際上刪除該存儲段。但無論此段是否仍在使用,該段標識符當即被刪除,因此不能再用shmat與該段鏈接
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
轉自:https://blog.csdn.net/ctthuangcheng/article/details/9271431
實踐經驗:unix內核並不像格式化磁盤同樣格式化共享內存,因此用戶必須人爲的把大共享內存劃分爲單個的小記錄塊。
常見應用模型:
1. 1-1模型