程序間通訊 共享記憶體 shmget

2021-08-24 20:25:02 字數 3119 閱讀 9303

介紹這一部分主要從它的幾個函式入手:

概念:共享記憶體是在物理記憶體上開闢一塊區域,這段被多個程序對映到自己程序的虛擬位址空間上,這些程序就可以直接訪問該共享記憶體區域,從而通過該區域實現各程序間的通訊。共享記憶體是程序間最快的一種通訊方式,乙個程序向共享記憶體上面寫資料,共享這塊記憶體的所有程序都可以看到其中的內容,這塊共享記憶體的頁面,出現在所用共享該頁面程序的頁表中,給人一種就是在訪問自己位址空間裡面的資料一樣。共享記憶體對映圖:

可以看到程序a和程序b共享了一塊記憶體,分別將共享記憶體所在的物理頁加入到自己的頁表中,訪問時就像訪問自己的東西一樣,所以它是最快的一種通訊方式。但是會有乙個問題,就是可能存在多個程序同時訪問這塊區域,此時共享記憶體區域就成了臨界資源,所以我們在使用共享記憶體時需要對它進行同步控制才能保證安全的使用。比如訊號量、加鎖等方式。

和其他ipc物件一樣,共享記憶體物件的獲取也是由key控制。每乙個新建立的共享記憶體物件都用乙個shmid_kernel的資料結構表示。系統中所用的shmid_kernel資料結構都儲存在shm_segs向量表中,該向量表中的每乙個元素都是乙個指向shmid_kernel資料結構的指標。shimd_kernel會包含共享記憶體的所用資訊。

linux為共享記憶體提供的四種操作

1、shmget函式:建立或者獲得乙個共享記憶體物件。它和其他兩種ipc機制一樣,程序在使用共享記憶體區域之前,必須通過系統呼叫sys_ipc(call值為shmget)建立乙個鍵值為key的共享記憶體物件,或者獲得已經存在的鍵值為key的某共享記憶體物件的引用識別符號。以後對共享記憶體物件的訪問都是通過該引用識別符號進行。看一下shmget函式定義:

int shmget(key_t key,int size,int shm***)
這裡key表示該共享記憶體的鍵值,size是該共享記憶體的大小(以位元組為單位),shm***是標誌(對該共享記憶體物件的特殊要求)。

過程如下:

計算size要占用的頁數,檢查其合法性

申請一塊記憶體用於建立shmid_kernel資料結構,(這裡申請的記憶體區域大小不包括真正的共享記憶體區,實際上,要等第乙個程序試圖訪問它的時候才真正建立共享記憶體區。

將shmid_kernel資料結構加入到向量表shm_segs中的合適位置

返回該共享記憶體物件的引用識別符號。

2、shmat函式:在獲得共享記憶體區域的引用識別符號後,還必須將共享記憶體區域對映到程序的虛擬位址空間中,然後才能使用該共享記憶體區域。系統呼叫sys_ipc(call值為shmat)用於共享記憶體區到程序虛擬位址空間的對映。看一下shmat函式的定義:

void * shmat(int shmid,const void *shmaddr,int shm***);
shmid:是shmget返回的共享記憶體物件的引用識別符號

sha***:對映標誌

過程如下:

根據shmid找到共享記憶體物件

檢查shmaddr的合法性(不能超過3g)

申請一塊記憶體用於建立資料結構vm_area_struct,填寫該結構

將其加入到程序的mm結構和該共享物件的vm_area_atruct中

注意:當程序第一次訪問共享虛擬記憶體的某頁時,因為所有的共享記憶體頁都還沒有分配,所以會發生乙個page fault異常。然後linux處理這個缺頁異常,將分配乙個物理頁,並為它建立乙個頁表條目。這個不僅進入當前程序的頁表,同時也存到shmid_kernel資料結構的頁表shm_pages中。

當下乙個程序訪問這塊記憶體時,發生page fault的時候,在檢視shmid_kelnel資料結構的shm_pages時,發現共享頁已經存在,它只需要把其中的頁表項填入到自己程序頁表的相應位置即可,而不需要重新建立物理頁,所以,是第乙個訪問共享記憶體的程序建立物理頁後其他訪問它的程序只需要把該頁加入到自己的虛擬位址空間就好了。

3、shmdt函式:當程序不需要共享這塊記憶體時,更新自己的頁表,共享記憶體對應的虛擬記憶體頁被標記為無效。當最後乙個程序分離這個共享記憶體時,共享記憶體頁被釋放,同時共享記憶體的shmid_kernel資料結構也被釋放。shmdt函式定義:

int shmdt(char *shmaddr)
shmaddr:表示程序要分離共享頁的起始虛擬位址。

該函式搜尋記憶體中所用的vm_area_atruct資料結構,找到位址shmaddr對應的那個,呼叫函式將其釋放,更新程序表中對應的頁表項。

4、shmctl函式:操作包括獲得共享記憶體物件的狀態、釋放共享記憶體物件資源等。這裡涉及到了同步控制問題。

下面看一下**示例:

#include #include #include 1.建立共享記憶體:

int shmget(key_t key,int size,int shm***);

引數說明:

key:用來表示新建或者已經存在的共享記憶體去的關鍵字。

size:建立共享記憶體的大小。

shm***:可以指定的特殊標誌。ipc_create,ipc_excl以及低九位的許可權。

eg:int shmid;

shmid=shmget(ipc_private,4096,ipc_create|ipc_excl|0660);

if(shmid==-1)

perror("shmget()");

2.連線共享記憶體

char *shmat(int shmid,char *shmaddr,int shm***);

引數說明

shmid:共享記憶體的關鍵字

eg:int shmid;

char *shmp;

shmp=shmat(shmid,0,0);

if(shmp==(char *)(-1))

perror("shmat()\n");

3.分離共享記憶體:當程式不再需要共享內後,我們需要將共享記憶體分離以便對其進行釋放,分離共享記憶體的函式原形如下:

int shmdt(char *shmaddr);

4.釋放共享記憶體

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

參考部落格:

程序間通訊 共享記憶體(shmget)

資料出處 當然只有mmap是可以的,不過由於各種不同的系統的架構不一樣,後來又經過整合,所以我們現在的linux有多種記憶體共享方案,下面在介紹一種非常常用的系統v記憶體方案。本人首先再在上次的基礎之上介紹乙個 國防科大的仁兄 本人在自己理解的基礎上一步一步去深入 include include i...

程序間通訊 共享記憶體

下面是自己寫的乙個簡單的共享記憶體的程序間通訊的例子。共享記憶體是用於程序間大量資料共享的一種方法。include include include include include include int main if buf1 shmat shmid,0,0 void 1 strcpy buf1,...

程序間通訊 共享記憶體

共享記憶體是被多個程序共享的一部分物理記憶體。共享記憶體是程序間共享資料的一種最快的方式,乙個程序向共享記憶體區域寫入資料,共享這個記憶體區域的所有程序就可以立刻看到其中的內容。共享記憶體實現分兩個步驟 建立共享記憶體,使用shmget函式 對映共享記憶體,使用shmat函式 共享記憶體是一種最為高...