共享內存及其用mmap實現共享內存


1、什麼是共享內存ide

顧名思義,共享內存就是容許兩個不相關的進程訪問同一個邏輯內存。共享內存是在兩個正在運行的進程之間共享和傳遞數據的一種很是有效的方式。不一樣進程之間共享的內存一般安排爲同一段物理內存。進程能夠將同一段共享內存鏈接到它們本身的地址空間中,全部進程均可以訪問共享內存中的地址,就好像它們是由用C語言函數malloc分配的內存同樣。若是某個進程向共享內存寫入數據,所作的改動將當即影響到能夠訪問同一段共享內存的任何其餘進程。函數

 

特別提醒:測試

共享內存並未提供同步機制,也就是說,在第一個進程結束對共享內存的寫操做以前,並沒有自動機制能夠阻止第二個進程開始對它進行讀取。因此咱們一般須要用其餘的機制來同步對共享內存的訪問,如信號量。spa

 

2、共享內存的使用,在Linux中提供了一組函數接口用於使用共享內存。指針

一、共享內存的建立函數orm

函數原型int shmget(key_t key,size_t size,int shmflg);對象

 

參數blog

(1)key:與信號量的semget函數同樣,程序須要提供一個參數(非0整數),有效的爲共享內存段名,返回一個與key相關的共享內存標識符(非負整數),用於後續的共享內存函數。調用失敗返回-1。繼承

 

不相關的進程能夠經過該函數的返回值訪問同一共享內存,它表明程序可能要使用的某個資源,程序對全部共享內存的訪問都是間接的,程序先經過調用shmget函數並提供一個鍵,再由系統生成一個相應的共享內存標識符(shmget函數的返回值),只有shmget函數才直接使用信號量鍵,全部其餘的信號量函數使用由semget函數返回的信號量標識符。接口


(2)Size:以字節爲單位指定須要共享的內存容量。

(3)Shmflg:權限標誌,它的做用與open函數的mode參數同樣,若是要想在key標識的共享內存不存在時,建立它的話,能夠與IPC_CREAT作或操做。共享內存的權限標誌與文件的讀寫權限同樣,舉例來講,0644,它表示容許一個進程建立的共享內存被內存建立者所擁有的進程向共享內存讀取和寫入數據,同時其餘用戶建立的進程只能讀取共享內存。

 

二、啓動對該共享內存的訪問,並把共享內存鏈接到當前進程的地址空間。

函數原型:void *shmat(int shm_id,const void *shm_addr,int shmflg)

 

參數;

(1)shm_id :由shmget函數返回的共享內存標識,

(2)shm_addr:指定共享內存鏈接到當前進程中的地址位置,一般爲空,表示讓系統選擇共享內存的地址,

(3)shm_flg:標誌位,一般爲0。

調用成功返回指向共享內存第一個字節的指針,失敗返回-1。

 

三、用於將共享內存從當前進程中分離。

函數原型:int shmdt(const void *shmaddr);

參數:爲shmat函數返回的地址空間,調用成功返回0,失敗時返回-1.

 

四、控制共享內存函數

函數原型:int shmctl(int shm_id,int command,struct shmid_ds *buf)

 

參數

(1)shm_id:共享內存標識符

(2)Command:採起的操做:

IPC_STAT:把shmid_ds結構中的數據設置爲共享內存的當前關聯值,即用共享內存的當前關聯值覆蓋shmid_ds的值。

IPC_SET:若是進程有足夠的權限,就把共享內存的當前關聯值設置爲shmid_ds結構中給出的值

IPC_RMID:刪除共享內存段

 

(3)buf:結構指針,指向共享內存模式和訪問權限的結構。

 shmid_ds結構以下:

wKioL1eXkPrC-X3KAABrM43-su4856.png-wh_50

測試代碼:

    shm.h

wKiom1eXkPrwnwlpAAA8iyABe6I062.png-wh_50

    shm.c

wKioL1eXkPqh5ZafAABX5YXYabk427.png-wh_50

wKioL1eXkPuh3xIsAAAoS0PXhUc131.png-wh_50

    test.c

wKiom1eXkPvCh9t6AABCZ6xTKdY190.png-wh_50

wKioL1eXkPvj80qvAAApIqyfG-k977.png-wh_50


共享內存mmap

一、特色:

1進程相關的

(2)與XSI共享內存同樣,須要與同步原語一塊兒使用

(3)只能是有共同祖先的進程才能使用

 

二、系統調用mmap()用於共享內存的方式:

(1)使用普通文件提供的內存映像:

適用於任何進程之間。此時,須要打開或建立一個文件,而後再調用mmap()

典型調用代碼以下:

fd=open(name, flag, mode); if(fd<0) ...

ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0);

(2)使用特殊文件提供匿名內存映像:

適用於具備親緣關係的進程之間:

適用於具備親緣關係的進程之間。因爲父子進程特殊的親緣關係,在父進程中先調用mmap(),而後調用fork()。那麼在調用fork()以後,子進程繼承父進程匿名映射後的地址空間,一樣也繼承mmap()返回的地址,這樣,父子進程就能夠經過映射區域進行通訊了。通常來講,子進程單獨維護從父進程繼承下來的一些變量。而mmap()返回的地址,卻由父子進程共同維護。對於具備親緣關係的進程實現共享內存最好的方式應該是採用匿名內存映射的方式

 

函數原型:void *mmap(void *addr,size_t len,int prot,int flag,int fd,off_t offset)

 

參數

一、addr:映射區的開始地址,設置爲0時表示系統決定映射區的起始地址

二、len:映射區的長度,單位爲字節

三、prot:指望的內存保護標誌,取一下幾個值:

PORT_EXEC:頁內容能夠被執行  PROT_READ:頁內容可被讀

PROT_WRITE:頁內容可被寫     PROT_NONE:頁內容不可訪問

四、fd:文件描述符。

五、offset:被映射對象內容的起點。

六、Flags(必需要有MAP_CHARED標誌):指定映射對象的類型,映射選項是否能夠和映射頁共存。

MAP_SHARED:與其餘全部映射這個對象的進程共享映射空間;

MAP_PRIVATE:創建一個寫入時拷貝的私有映射。內存區域的寫入不會影響到原文件。

MAP_FIXED:使用指定的映射起始地址

測試代碼:

mmap.c

wKiom1eXkgbg41VBAABNRS3WFWQ495.png-wh_50

wKiom1eXkgayKSpfAAAqc3yxplE056.png-wh_50

wKioL1eXkgahAa1vAAAPoLtcDtg055.png-wh_50

運行結果:

wKioL1eXkgXBl5-8AAAGKGUVwY4592.png-wh_50

相關文章
相關標籤/搜索