什麼是共享內存?
共享內存就是允許兩個不相關的進程訪問同一塊物理內存。進程可將同一段共享內存連接到它們自己的地址空間中,所有進程都可以訪問共享內存中的地址。如果某一個進程向共享內存中寫入數據,所做的改動將立即影響到可以訪問同一段共享內存的其他進程。
函數接口
(1)創建共享內存
函數原型:int shmget(key_t key,size_t size,int shmflg)
key :由ftok()函數返回的標識符
size:以字節爲單位的需要共享的內存容量
shmflg:
IPC_CREAT:單獨使用,若共享內存不存在,創建,否則,直接打開。
IPC_EXCL:單獨使用無意義
IPC_CREAT | IPC_EXCL:若不存在,創建,否則返回-1.
(2)對共享內存的訪問
函數原型:void *shmat(int shm_id,const void* shm_addr,int shmflg)
shm_id:是shmget函數返回的標識符
shm_addr:指定共享內存連接到當前進程中的地址位置,通常爲NULL,表示讓系統來選擇共享內存的地址
shm_flg:IPC_CREAT或爲0
返回值:成功時返回指向共享內存的指針,失敗返回-1.
(3)將共享內存從當前過程中分離
函數原型:int shmdt(const void* shmaddr)
shmaddr:shmat函數的返回值
返回值:成功返回0,失敗返回-1.
(4)控制內存共享
函數原型:int shmctl(int shm_id,int cmd,struct shmid_ds* buf)
shm_id: shmget函數返回的標識符
cmd:
IPC_STAT:把shmid_ds結構中的數據設置爲共享內存的當前關聯值,即用共享內存的當前關聯值覆蓋shmid_ds的值。
IPC_SET:如果進程有足夠的權限,就把共享內存的當前關聯值設置爲shmid_ds結構中給出的值
IPC_RMID:刪除共享內存段
“shm.h”
“shm.c”
“test.c”
運行結果:
結果分析: 每隔一秒打印root的共享內存的情況。
首先由父進程創建共享內存,父進程創建子進程,父子進程都關聯了共享內存,關聯的個數由0變爲2,因父進程休息時間短,取消關聯,關聯個數變爲1,最後子進程也取消關聯,關聯個數變爲0,最後將共享內存destory。。。
3.mmap函數
mmap將一個文件或者其他對象映射進內存。mmap也可以實現共享內存。mmap函數調用使得進程之間通過映射同一個文件實現共享內存。文件被映射到進程地址空間後,進程可以像讀寫內存一樣對文件進行操作。
函數原型:void* mmap(void* addr,size_t length,int prot,int flags,int fd,off_t offset);
addr:映射區的開始地址,設置爲0時表示系統決定映射區的起始地址
length:映射區的長度。長度單位爲字節
prot:期望的內存保護標誌。取以下幾個值:
PORT_EXEC:頁內容可以被執行 PORT_READ:頁內容可以被讀取
PORT_WRITE:頁內容可以被寫入 PROT_NONE:頁內容不可訪問
flag:指定映射對象的類型,映射選項與映射頁是否可以共享。
MAP_SHARED:與其他所有映射這個對象的進程共享映射空間。
MAP_PRIVATE:建立一個寫入時拷貝的私有映射。內存區域的寫入不會影響到原文件。
MAP_FIXED :使用指定的映射起始地址,如果由start和len參數指定的內存區重疊於現存的映射空 間,重疊部分將會被丟棄。如果指定的起始地址不可用,操作將會失敗。
fd: 有效的文件描述符。返回,由一般open()函數,其值可以設置爲-1.此時需要指定flags參數爲 MAP_ANON,表明進行的是匿名映射。
offset:被映射對象內容的起點。
返回值:成功,返回被映射區的指針;失敗,返回-1.