共享內存

共享內存區域是被多個進程共享的一部分物理內存

多個進程都可把該共享內存映射到自己的虛擬內存空間,所有用戶空間的進程若要操作共享內存,都要將其映射到自己虛擬內存空間中,通過映射的虛擬內存空間地址去操作共享內存,從而達到進程間的數據通信。

共享內存是進程間共享數據的一種最快的方法,一個進程向共享內存區域寫入了數據,共享這個內存區域的所有進程就可以立刻看到其中的內容。

本身不提供同步進制,可通過信號量進行同步

提升數據處理效率,一種效率最高IPC機制

 

實現共享內存的步驟如下:

(1) 創建內存共享區 

進程1通過操作系統提供的api從內存中申請一塊共享區域,linux系統中可以通過shmget函數實現,生成的共享內存塊與某個特定的key進行綁定。

(2) 映射共享內存到進程1中

在linux環境中,可以通過shmat實現。

(3)映射共享內存到進程2中

進程2通過進程1的shmget函數和同一個key值,然後執行shmat,將這個內存映射到進程2中。

(4)進程1與進程2中相互通信

共享內存實現兩個映射後,可以利用該區域進行信息交換,由於沒有同步機制,需要參與通信的進程自己協商處理。

(5)撤銷內存映射關係

完成通信之後,需要撤銷之前的映射操作,通過shmdt函數實現。

(6)刪除共享內存區

在linux中通過shctl函數來實現。

具體函數介紹:

 

1)創建共享內存

所需頭文件:

#include <sys/ipc.h>

#include <sys/shm.h>

 

int shmget(key_t key, size_t size,int shmflg);

功能:

創建或打開一塊共享內存區。

參數:

key進程間通信鍵值,ftok() 的返回值。

size:該共享存儲段的長度(字節)。

shmflg:標識函數的行爲及共享內存的權限,其取值如下:

IPC_CREAT:如果不存在就創建
IPC_EXCL:  如果已經存在則返回失敗
位或權限位:共享內存位或權限位後可以設置共享內存的訪問權限,格式和 open() 函數的 mode_t 一樣(open() 的使用請點此鏈接),但可執行權限未使用。

返回值:

成功:共享內存標識符。

失敗:-1。

2)共享內存映射

所需頭文件:

#include <sys/types.h>

#include <sys/shm.h>

 

void *shmat(int shmid, const void *shmaddr, int shmflg);

功能:

將一個共享內存段映射到調用進程的數據段中。簡單來理解,讓進程和共享內存建立一種聯繫,讓進程某個指針指向此共享內存。

參數:

shmid:共享內存標識符,shmget() 的返回值。

shmaddr:共享內存映射地址(若爲 NULL 則由系統自動指定),推薦使用 NULL

shmflg:共享內存段的訪問權限和映射條件( 通常爲 0 ),具體取值如下:

0:共享內存具有可讀可寫權限。
SHM_RDONLY:只讀。
SHM_RND:(shmaddr 非空時纔有效)

返回值:

成功:共享內存段映射地址( 相當於這個指針就指向此共享內存 )
失敗:-1

 

3)解除共享內存映射

所需頭文件:

#include <sys/types.h>
#include <sys/shm.h>

 

int shmdt(const void *shmaddr);

功能:

將共享內存和當前進程分離( 僅僅是斷開聯繫並不刪除共享內存,相當於讓之前的指向此共享內存的指針,不再指向)。

參數:

shmaddr:共享內存映射地址。

返回值:

成功:0

失敗:-1

 

4)共享內存控制

所需的頭文件:

#include <sys/ipc.h>

 

#include <sys/shm.h>

 

 

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

功能:

共享內存屬性的控制。

參數:

shmid:共享內存標識符。

cmd:函數功能的控制,其取值如下:

IPC_RMID:刪除。(常用 )
IPC_SET:設置 shmid_ds 參數,相當於把共享內存原來的屬性值替換爲 buf 裏的屬性值。
IPC_STAT:保存 shmid_ds 參數,把共享內存原來的屬性值備份到 buf 裏。
SHM_LOCK:鎖定共享內存段( 超級用戶 )。
SHM_UNLOCK:解鎖共享內存段。

 

SHM_LOCK 用於鎖定內存,禁止內存交換。並不代表共享內存被鎖定後禁止其它進程訪問。其真正的意義是:被鎖定的內存不允許被交換到虛擬內存中。這樣做的優勢在於讓共享內存一直處於內存中,從而提高程序性能。

 

buf:shmid_ds 數據類型的地址(具體類型請點此鏈接 ),用來存放或修改共享內存的屬性。

返回值:

成功:0

失敗:-1

實例:利用共享內存實現銀行取款(Linux多線程的實例)

補充資料:https://blog.csdn.net/qq_33336155/article/details/51880897

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章