Linux IPC之共享記憶體

2021-07-09 19:50:35 字數 3512 閱讀 9310

程序都有自己的虛擬位址空間(每個程序的虛擬位址空間都不一樣),自己只能操作自己的位址空間(虛擬位址空間),這時如何實現程序間的資料交換,這裡核心給我們提供了介面,讓多個程序共同操作同塊特殊的記憶體區域,這就實現了資料交換

共享記憶體區域是被多個程序共享的一部分物理記憶體。如果多個程序都把該記憶體區域對映到自己的虛擬位址空間,則這些程序就都可以直接訪問該共享記憶體區域,從而可以通過該區域進行通訊。共享記憶體是程序間共享資料的一種最快的方法,乙個程序向共享記憶體區域寫入了資料,共享這個記憶體區域的所有程序就可以立刻看到其中的 內容。這塊共享虛擬記憶體的頁面,出現在每乙個共享該頁面的程序的頁表中。但是它不需要在所有程序的虛擬記憶體中都有相同的虛擬位址。 

現在的ipc屬於system v這個標準

posix 標準

物理記憶體是通過虛擬記憶體來操作的

共享記憶體區域:一塊特殊的物理記憶體區域

只要一提本程序,就屬於虛擬位址空間

共享記憶體允許

同時對映到

乙個或多個程序中,通過它們的虛擬位址空間的記憶體進行通訊(這段記憶體同時出現在多個人的虛擬位址空間中)

共享記憶體的優勢:可以一人寫,n個人讀,而管道只能是兩個人之間的(一條)

ipcs :檢視共享記憶體

ipcrm -m 共享記憶體標誌符(類似於程序pid)  :刪除共享記憶體

如果在字元指標的位置要寫整型資料,得先將指標強轉成整型指標,然後再放,這樣指標偏移時才能以乙個整型資料的位寬進行偏移(放完之後該偏移的偏移)

共享記憶體

函式定義如下:

#include

#include

#include

key_t ftok(const

char *pathname, int proj_id);

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

void *shmat(int shmid, const

void *shmaddr, int shm***);

int shmdt(const

void *shmaddr);

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

ftok用於建立乙個關鍵字,可以用該關鍵字關聯乙個共享記憶體段。

key_t ftok(

const

char *pathname, 

int proj_id);

引數pathname為乙個全路徑檔名(絕對or相對),並且該檔案必須可訪問。傳入路徑(file)是為了讓其產生乙個唯一的key,並在這個key相關聯的共享記憶體中進行操作,並非為了使用file

引數proj_id通常傳入一非0字元,可以直接傳1

通過pathname和proj_id組合可以建立唯一的key

如果呼叫成功,返回一關鍵字,否則返回-1

函式shmget用於建立或開啟一共享記憶體段,該記憶體段由函式的第乙個引數唯一建立。函式成功,則返回乙個唯一的共享記憶體標識號(相當於程序號,唯一的標識著共享記憶體),失敗返回

-1。int shmget(key_t key, 

int size, 

int shm***);

引數key是乙個與共享記憶體段相關聯關鍵字,如果事先已經存在乙個與指定關鍵字關聯的共享記憶體段,則直接返回該記憶體段的標識,表示開啟,如果不存在,則建立乙個新的共享記憶體段。

key的值既可以用

ftok

函式產生,也可以是

ipc_

private

(用於建立乙個只屬於建立程序的共享記憶體,主要用於父子通訊)

,表示總是建立新的共享記憶體段;

引數size指定共享記憶體段的大小,以位元組為單位;

引數shm***是一掩碼合成值,可以是訪問許可權值與

(ipc_creat

或ipc_excl)的合成。ipc_creat表示如果不存在該記憶體段,則建立它;如果存在,則返回。ipc_excl表示如果該記憶體段存在,則函式返回失敗結果(-1)。如果呼叫成功,返回記憶體段標識,否則返回-1

ipc_creat key :如果存在,則返回記憶體標誌符;假如key在ipcs中不存在,則單獨建立乙個記憶體標誌符.

ipc_creat|ipc_excl:這種方式只能建立,不能獲取

為什麼要用shmget拿key去獲取(建立)共享記憶體,因為共享記憶體是系統資源,當程序結束時,共享記憶體並不會消失,即使建立之後別人沒有用 。通過命令ipcs可以檢視系統的一系列共享記憶體。因為是整個系統所共有的,所以key只能是唯一的

key是ipc_

private:

key的值用

ftok

函式產生:

key是乙個key_t型的數:

函式shmat將共享記憶體段對映到程序空間的某一位址(只要一提程序,則為虛擬位址)。

void

*shmat(

intshmid,

const

void

*shmaddr,

intshm***);

引數shmid是共享記憶體段的標識  

通常應該是

shmget

的成功返回值

引數shmaddr指定的是共享記憶體連線到當前程序中的位址位置(虛擬位址)

。通常是null

,表示讓系統來選擇共享記憶體出現的位址。

引數shm***是一組位標識,通常為0即可。

如果呼叫成功,返回對映共享記憶體的首位址(非程序的首位址),否則返回(char *)-1。

//以下表示在共享記憶體中進行操作,圖1是通過在對映後的虛擬記憶體段(共享記憶體對映到該程序的一段虛擬位址)寫資料,實際上是在共享記憶體(一塊特殊的實體地址)中寫;

圖2通過在

對映後的虛擬記憶體段上讀資料,實際上是在共享記憶體中讀資料,從而實現兩個程序的資料交換

//其它進行如果要訪問該段共享程序,可以在shmget中輸入這塊共享記憶體指定的key

函式shmdt用於將共享記憶體段與程序空間分離。

intshmdt(

const

void

*shmaddr);

引數shmaddr通常為

shmat

的成功返回值。

函式成功返回

0,失敗時返回

-1.注意,將該程序與共享記憶體分離(並沒刪除它),只是使得該共享記憶體對當前程序不再可用。 函式

shmctl是共享記憶體的控制函式,可以用來刪除共享記憶體段。

intshmctl(

intshmid,

intcmd,

struct

shmid_ds *buf);

引數shmid是共享記憶體段標識 

通常是shmget

的成功返回值

引數cmd是對共享記憶體段的操作方式,可選為ipc_stat(把共享記憶體的屬性資訊讀取到後面的結構體),ipc_set,

ipc_rmid

。通常為ipc_rmid

,表示刪除共享記憶體段(在程式中對共享記憶體進行刪除)。

引數buf是表示共享記憶體段的資訊結構體資料,通常為

null

Linux IPC 共享記憶體

posix.1提供了兩種在無親緣關係的程序間共享記憶體的方式 1 記憶體對映檔案 由open函式開啟 乙個檔案 由mmap函式把得到的描述符對映到當前程序位址空間中。2 共享記憶體區物件 由shm open開啟乙個posix.1 ipc名字 通常是檔案系統中的乙個路徑名 所返回的描述符由mmap函式...

linux ipc機制 共享記憶體

17.shmat 功能 聯接共享記憶體的操作.語法 include include include void shmat shmid,shmaddr,shm int shmid void shmaddr int shmid 說明 將由shmid指示的共享記憶體聯接到呼叫程序的資料段中.被聯接的段放在...

Linux IPC 之訊息佇列

system v or posix 該使用哪個呢,這是個問題 相對而言,我更傾向於後者 posix mq posix mq 的概況看這裡 man mq overview 簡單的實現 include include include include define my mq name my test m...