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

2021-07-24 19:34:35 字數 3533 閱讀 1024

**: 

1. 共享記憶體:

共享記憶體方式可以在多個程序直接共享資料,因為其直接使用記憶體,不要多餘的拷貝,是速度最快的ipc方式;

共享記憶體有兩種實現方式,使用mmap和shm方式,如下圖:

(1) mmap方式是將檔案與程序位址空間進行對映,對實際物理記憶體影響小;

(2) shm方式是將每個程序的共享記憶體與實際物理儲存器進行對映,對實際物理記憶體影響大;

由於xsi ipc自身缺點,所以建議使用mmap來實現共享記憶體;

2. mmap相關函式原型:

#include void *mmap(void *addr, size_t len, int prot, int flag, int

filedes, off_t off);

ret = 成功返回對映區域開始位址,失敗返回map_failed

addr-引數用來指定對映區域的起始位址。通常設定為0,表示有系統選擇對映區域的起始位置;

filedes-要對映檔案的描述符。在對映檔案到位址空間之前,先要開啟檔案;

len-對映的位元組數;

off-要對映位元組在檔案中的起始偏移量;

prot-對對映儲存區的保護要求,指定為prot_none(不可訪問), prot_read(可讀), prot_write(可寫), prot_exec(可執行)的任意組合或者按位或;

但是對於對映儲存區的保護要求不能超過檔案open的許可權,比如檔案是唯讀開啟的,則不能指定prot_write;

flag-map_fixed 返回值必須等於addr,如果未制定此標誌,addr非0,則作為一種建議,核心不保證會使用該位址。為了獲得最大的可移植性,建議addr指定為0;

map_shared 說明了本程序對對映區域進行儲存操作的配置。此標誌指定儲存操作修改對映檔案,也就是相當於對該檔案執行write;

map_private 本標誌說明對對映區儲存操作會建立該對映的乙個副本。所以後續操作都會引用該副本,而不是原始檔案;

map_sahred 和 map_private 必須指定其一,但是不能同時指定;

修改現有對映區的許可權,與上面mmap中的prot欄位相同;

#include int mprotect(void *addr, size_t len, int

prot);

ret = 成功返回0,失敗返回-1

如果共享記憶體中的頁已被修改,則可以呼叫msync將該頁沖洗到對映的檔案中;

如果對映是私有的,那麼不修改對映檔案;

#include int msync(void *addr, size_t len, int

flags);

ret = 成功返回0 失敗返回-1

flags- ms_async和ms_sync必選其一;

ms_async-非同步sync,無需等待,系統排程;

ms_sync-同步sync,需要等到操作完成;

ms_invalidate-可選標誌,通知作業系統丟棄沒有同步的頁;--一般不使用;

程序終止,或者呼叫munmap,記憶體對映就被自動解除,關閉檔案描述符filedes並不會解除對映;

呼叫munmap不會是對映記憶體內容寫到磁碟檔案,share型別寫磁碟是核心根據演算法自動執行,private則丟棄修改;

#include int

munmap(caddr_t addr, size_t len);

ret-成功返回0 失敗返回-1

3.  檔案對映到程序位置:

檔案對映到程序位址空間中堆和棧直接的一段記憶體。

4. 子程序影響:

fork之後,因為子程序複製父程序的位址空間,而儲存對映是該位址空間的一部分,所以子程序繼承了該儲存對映區域,但是當呼叫了exec函式組之後的新程式則不繼承該對映區;

測試**:--測試兩個程序通過mmap對映資訊,測試共享時,資料情況,和共享後資料情況;

common.h

1 #include 2 #include 3 #include 4 #include 5 #include 67

#define mmap_file "/var/tmp/test_mmap"

8#define name_len 64

910 typedef struct

book book_t;

mmap_proc1.c -- 程序1,做對映,對映超過檔案長度的區域

1 #include "

common.h"2

3int main(int argc, char *argv)413

14if (lseek(fd, sizeof(book_t) * 2 - 1, seek_set) < 0)19

20 write(fd, "", 1

);21

22if ((book = (book_t *)mmap(null, sizeof(book_t) * 4, prot_read|prot_write, map_shared, fd, 0)) ==map_failed)

2627

close(fd);

2829

for (i = 0; i < 4; i++);

31 snprintf (name, 15, "

book-%d

", i);

3233 (*(book + i)).id =i;

34 strncpy((*(book + i)).name, name, name_len - 1

);35}36

37 sleep(10

);38

39 munmap(book, sizeof(book_t) * 4

);40

41return0;

42 }

mmap_proc2.c -- 程序2,做對映,對映與程序1相同區域

1 #include "

common.h"2

3int main(int argc, char *argv)413

14if ((book = (book_t *)mmap(null, sizeof(book_t) * 4, prot_read|prot_write, map_shared, fd, 0)) ==map_failed)

1819

close(fd);

2021

for (i = 0; i < 4; i++)

2425 munmap(book, sizeof(book_t) * 4

);26

27return0;

28 }

程序間通訊 三 共享記憶體

共享記憶體是linux下倆程序通訊的一種方式,主要功能是讓兩個程序的虛擬位址都對映到同一片實體地址上,就可以通過這片實體地址進行資料的互動 mmap函式要求核心建立乙個新的虛擬記憶體區域,最好是從位址start開始的乙個區域,並將檔案描述符df指定的物件的乙個連續的片對映到這個新的區域,連續的物件片...

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

共享記憶體區是最快的ipc形式。一旦這樣的記憶體對映到共享他的程序的位址空間,這些程序間資料傳遞不再涉及到核心,換句話說就是程序不再通過執行進入核心的系統呼叫來傳遞彼此的資料。共享記憶體示意圖 共享記憶體資料結構 struct shmid ds 相關函式shmget函式 建立共享記憶體 int sh...

Linux程序間通訊 共享記憶體

共享記憶體是執行在同一臺機器上的程序間通訊最快的方式,因為資料不需要在不同的程序間複製。通常由乙個程序建立一塊共享記憶體區,其餘程序對這塊記憶體區進行讀寫。共享記憶體往往與其它通訊機制,如訊號量結合使用,來達到程序間的同步及互斥。首先要用的函式是shmget,它獲得乙個共享儲存識別符號。i nclu...