共享記憶體的通訊原理

2021-08-28 13:38:40 字數 3641 閱讀 1402

共享記憶體是system v版本的最後乙個程序間通訊方式。共享記憶體,顧名思義就是允許兩個不相關的程序訪問同乙個邏輯記憶體,共享記憶體是兩個正在執行的程序之間共享和傳遞資料的一種非常有效的方式。不同程序之間共享的記憶體通常為同一段物理記憶體。程序可以將同一段物理記憶體連線到他們自己的位址空間中,所有的程序都可以訪問共享記憶體中的位址。如果某個程序向共享記憶體寫入資料,所做的改動將立即影響到可以訪問同一段共享記憶體的任何其他程序。

下面就 shared memory 的ipc作以闡述與分析。

在linux中,每個程序都有屬於自己的程序控制塊(pcb)和位址空間(addr space),並且都有乙個與之對應的頁表,負責將程序的虛擬位址與實體地址進行對映,通過記憶體管理單元(mmu)進行管理。兩個不同的虛擬位址通過頁表對映到物理空間的同一區域,它們所指向的這塊區域即共享記憶體。

共享記憶體的通訊原理示意圖:

對於上圖我的理解是:當兩個程序通過頁表將虛擬位址對映到實體地址時,在實體地址中有一塊共同的記憶體區,即共享記憶體,這塊記憶體可以被兩個程序同時看到。這樣當乙個程序進行寫操作,另乙個程序讀操作就可以實現程序間通訊。但是,我們要確保乙個程序在寫的時候不能被讀,因此我們使用訊號量來實現同步與互斥。

對於乙個共享記憶體,實現採用的是引用計數的原理,當程序脫離共享儲存區後,計數器減一,掛架成功時,計數器加一,只有當計數器變為零時,才能被刪除。當程序終止時,它所附加的共享儲存區都會自動脫離。

借助上圖說明:proc a 程序給記憶體中寫資料, proc b 程序從記憶體中讀取資料,在此期間一共發生了兩次複製

(1)proc a 到共享記憶體       (2)共享記憶體到 proc b

因為直接在記憶體上操作,所以共享記憶體的速度也就提高了。

1.檢視系統中的共享儲存段

ipcs -m
2.刪除系統中的共享儲存段

ipcrm -m [shmid]
3.shmget ( ):建立共享記憶體

int shmget(key_t key, size_t size, int shm***);
[引數key]:由ftok生成的key標識,標識系統的唯一ipc資源。

[引數size]:需要申請共享記憶體的大小。在作業系統中,申請記憶體的最小單位為頁,一頁是4k位元組,為了避免記憶體碎片,我們一般申請的記憶體大小為頁的整數倍。

[引數shm***]:如果要建立新的共享記憶體,需要使用ipc_creat,ipc_excl,如果是已經存在的,可以使用ipc_creat或直接傳0。

[返回值]:成功時返回乙個新建或已經存在的的共享記憶體識別符號,取決於shm***的引數。失敗返回-1並設定錯誤碼。

4.shmat ( ):掛接共享記憶體

void *shmat(int shmid, const void *shmaddr, int shm***);
[引數shmid]:共享儲存段的識別符號。

[引數shm***]:若指定了shm_rdonly位,則以唯讀方式連線此段,否則以讀寫方式連線此段。

5.shmdt ( ):去關聯共享記憶體

當乙個程序不需要共享記憶體的時候,就需要去關聯。該函式並不刪除所指定的共享記憶體區,而是將之前用shmat函式連線好的共享記憶體區脫離目前的程序。

int shmdt(const void *shmaddr);
[返回值]:成功返回0,並將shmid_ds結構體中的 shm_nattch計數器減1;出錯返回-1。

6.shmctl ( ):銷毀共享記憶體

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
[引數shmid]:共享儲存段識別符號。

[引數cmd]:指定的執行操作,設定為ipc_rmid時表示可以刪除共享記憶體。

[引數*buf]:設定為null即可。

[返回值]:成功返回0,失敗返回-1。

我們用server來建立共享儲存段,用client獲取共享儲存段的識別符號,二者關聯起來之後server將資料寫入共享儲存段,client從共享區讀取資料。通訊結束之後server與client斷開與共享區的關聯,並由server釋放共享儲存段。

comm.h

#ifndef _comm_h__

#define _comm_h__

#include#include#include#include#define pathname "."

#define proj_id 0x6666

int createshm(int size);

int destroyshm(int shmid);

int getshm(int size);

#endif

comm.c

#include"comm.h"

static int commshm(int size,int flags)

int shmid = 0;

if((shmid = shmget(key,size,flags)) < 0)

return shmid;

}int destroyshm(int shmid)

return 0;

}int createshm(int size)

int getshm(int size)

client.c

#include"comm.h"

int main()

shmdt(addr);

sleep(2);

return 0;

}

server.c

#include"comm.h"

int main()

shmdt(addr);

sleep(2);

destroyshm(shmid);

return 0;

}

makefile

//makefile

.phony:all

all:server client

client:client.c comm.c

gcc -o $@ $^

server:server.c comm.c

gcc -o $@ $^

.phony:clean

clean:

rm -f client server

執行結果:

總結:(1)優點:我們可以看到使用共享記憶體進行程序之間的通訊是非常方便的,而且函式的介面也比較簡單,資料的共享還使程序間的資料不用傳送,而是直接訪問記憶體,加快了程式的效率。

(2)缺點:共享記憶體沒有提供同步機制,這使得我們在使用共享記憶體進行程序之間的通訊時,往往需要借助其他手段來保證程序之間的同步工作。

程序通訊 共享記憶體

定義 共享記憶體,就是通過核心操作,在記憶體上開闢一塊供多個程序共同訪問的記憶體塊。這塊記憶體塊的建立和 銷毀是由核心來控制 當然,也可以在程序內部呼叫系統庫函式來建立和銷毀,類似於訊息機制和訊號 量機制 在這個記憶體塊上,程序可以像操作記憶體一樣操作共享區記憶體。作用 第乙個,就是提供程序間大資訊...

程序通訊共享記憶體

共享記憶體是允許多個程序共享記憶體 共享記憶體結構 struct shmid ds struc ipc permshm perm 指向該記憶體指標 int shm segsz 共享記憶體的大小 ushort shm lkcnt 共享記憶體被鎖定的時間 pid t shm cpid 最近呼叫shomp...

linux通訊 共享記憶體

共享記憶體是效率最高的程序間通訊方式 程序可以直接讀寫記憶體,不需要任何資料的拷貝。多個程序共享一段記憶體,因此與需要依靠某種同步機制,如互斥鎖和訊號燈等。建立開啟共享記憶體 shmget share memory get 對映共享記憶體 shmat share memory attach 撤銷共享...