Linux共享記憶體實現方法

2021-10-24 01:34:35 字數 4326 閱讀 7831

共享記憶體

1. 共享記憶體概述

共享記憶體是允許兩個不相關的程序訪問同乙個邏輯記憶體的程序間通訊方法,是在兩個正

在執行的程序之間共享和傳遞資料的一種非常有效的方式。

不同程序之間共享的記憶體通常安排為同一段物理記憶體。程序可以將同一段共享記憶體連線

到它們自己的位址空間中,所有程序都可以訪問共享記憶體中的位址,就好像它們是由用 c

語言 malloc()分配的記憶體一樣。兩個程序使用共享記憶體通訊機制如圖 所示。

共享記憶體示意圖

posix 共享記憶體區涉及四個主要步驟:

 指定乙個名字引數呼叫 shm_open,以建立乙個新的共享記憶體區物件(或開啟乙個

以存在的共享記憶體區物件);

 呼叫 mmap 把這個共享記憶體區對映到呼叫程序的位址空間;

 呼叫 munmap() 取消共享記憶體對映;

 呼叫 shm_unlink()函式刪除共享記憶體段。

在編譯 posix 共享記憶體應用程式時需要加上-lrt 引數。

2. 開啟或建立乙個共享記憶體區

shm_open()函式用來開啟或者建立乙個共享記憶體區,兩個程序可以通過給 shm_open()

函式傳遞相同的名字以達到操作同一共享記憶體的目的。它的原型如下:

#include

#include

#include

int shm_open(const char *name, int oflag, mode_t mode);

函式成功返回建立或開啟的共享記憶體描述符,與檔案描述符相同作用,供後續操作使用,

失敗返回-1。

 引數 name 為指定建立的共享記憶體的名稱,其它程序可以根據這個名稱來開啟共享

記憶體; 引數 oflag 為以下值的或值:

 o_rdonly:共享記憶體以唯讀方式開啟;

 o_rdwr:共享記憶體以可讀寫方式開啟;

 o_creat:共享記憶體不存在才建立;

 o_excl:如果指定了 o_creat,但共享記憶體已經存在時返回錯誤;

 o_trunc:如果共享記憶體已存在則將大小設定為 0;

引數 mode 只有指定 o_creat 才有效指出,指出共享記憶體的許可權,與 open()函式

類似。注意:新建立或開啟的共享記憶體大小預設為 0,需要設定大小才能使用。

3. 刪除共享記憶體

當使用完共享記憶體後,需要將其刪除,以便釋放系統資源,可通過 shm_unlink()函式完

成。shm_unlink()函式原型如下:

#include

#include

#include

int shm_unlink(const char *name);

函式成功返回 0,否則返回-1。引數 name 為共享記憶體的名字。

4. 設定共享記憶體大小

建立乙個共享記憶體後,預設大小為 0,所以需要設定共享記憶體大小。ftruncate()函式可用

來調整檔案或者共享記憶體的大小,它的原型如下:

#include

#include

int ftruncate(int fd, off_t length);

函式成功返回 0,失敗返回-1。

引數 fd 為需要調整的共享記憶體或者檔案,length 為需要調整的大小。

5. 對映共享記憶體

建立共享記憶體後,需要將共享記憶體對映到呼叫程序的位址空間,可通過 mmap()函式來

完成。mmap()函式原型如下:

#include

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

函式成功返回對映後指向共享記憶體的虛擬位址,失敗返回 map_failed 值。

引數如下:

 addr:指向對映儲存區的起始位址,通常將其設定為 null,這表示由系統選擇該

對映區的起始位址;

 len:對映的位元組數;

 port:對對映儲存區的保護要求,對指定對映儲存區的保護要求不能超過檔案 open

模式訪問許可權。它可以為以下值的或值:

 prot_read:對映區可讀);

 prot_write:對映區可寫;

 ,prot_exec:對映區可執行;

 prot_none:對映區不可訪問。

flag:對映標誌位,可為以下值的或值:

 map_fixed:返回值必須等於 addr。因為這不利於可移植性,所以不鼓勵使

用此標誌;

 map_shared:多個程序對同乙個檔案的對映是共享的,乙個程序對對映的

記憶體做了修改,另乙個程序也會看到這種變化;

 map_private:多個程序對同乙個檔案的對映不是共享的,乙個程序對對映

的記憶體做了修改,另乙個程序並不會看到這種變化。

 fd:要被對映的檔案描述符或者共享記憶體描述符;

 offset:要對映位元組在檔案中的起始偏移量。

6. 取消共享記憶體對映

已經建立的共享記憶體對映,可通過 munmap()函式用來取消。munmap()函式原型如下:

#include

int munmap(void *addr, size_t length);

函式成功返回 0,否則返回-1;

引數 addr 為 mmap()函式返回的位址,length 是對映的位元組數。取消對映後再對對映地

址訪問會導致呼叫程序收到 sigse** 訊號。

7. 共享記憶體範例

兩個範例實現了兩個無關程序使用共享記憶體進行通訊

的功能。乙個程序往共享記憶體的起始位址寫入乙個整型資料 18,另乙個程序則檢測該區域

的資料,如果不是 18 則繼續等待,直到該區域的資料變化為 18。

所示**完成共享記憶體寫操作:

先建立共享記憶體,

設定大小並完成對映,

隨後往共享記憶體起始位址寫入乙個值為 18 的整型資料,最後取消和刪除共享記憶體。

sample10_write 共享記憶體寫資料

#include

#include

#include

#include

#include

#include

#include

#define shmsize

10#define shmname "shmtest"

/* 共享記憶體大小,10 位元組 */

/* 共享記憶體名稱 */

int main()

ftruncate(fd, shmsize);

/* 設定大小為 shmsize

/* 設定共享記憶體大小*/

ptr = mmap(null, shmsize, prot_read | prot_write, map_shared, fd, 0);

if (ptr == map_failed)

*ptr = 18; /* 往起始位址寫入 18 */

munmap(ptr, shmsize); /* 取消對映 */

shm_unlink(shmname); /* 刪除共享記憶體 */

return 0;

}程式清單則實現了共享記憶體的讀取操作:首先建立共享記憶體,設定大小並對映共

享記憶體後,檢測共享記憶體首位元組資料是否為 18,如果不是,繼續等待,否則列印顯示,並

取消和刪除共享記憶體。

程式清單  共享記憶體讀資料

#include

#include

#include

#include

#include

#include

#include

#define shmsize

10/* 共享記憶體大小,10 位元組 */

#define shmname "shmtest"

/* 共享記憶體名稱

*/int main()

ptr = mmap(null, shmsize, prot_read | prot_write, map_shared, fd, 0);/*對映共享記憶體*/

if (ptr == map_failed)

ftruncate(fd, shmsize);

/* 設定共享記憶體大小

while (*ptr != 18) {

/* 讀起始位址,判斷值是否為 18

sleep(1);

*/*/

/* 不是 18,繼續讀取 */

printf("ptr : %d\n", *ptr); /* 資料是 18,列印顯示 */

munmap(ptr, shmsize); /* 取消記憶體對映 */

shm_unlink(shmname);

Linux 共享記憶體

一 概念 共享記憶體是被多個程序共享的一部分物理記憶體,是程序間共享資料的最快的一種方法。二 實現 分為兩個步驟 1 建立共享記憶體。2 對映共享記憶體。1 建立 int shmget key t key,int size,int shm 當key的取值為 ipc private 時,將建立一塊新的...

linux共享記憶體

linux共享記憶體使用 標頭檔案 include 1 建立共享記憶體 int shmget key t key,size t size,int shm 建立成功以後會返回乙個共享記憶體id,建立失敗返回 1。2 獲取共享記憶體 void shmat int shmid,const void shm...

linux 共享記憶體

共享記憶體解決的問題是 任意兩個程序之間的通訊如果是有名管道,是沒有辦法對管道中間的資料獲取讀和寫操作的,只能是兩段的資料,那麼如何對所有的資料進行操作 共享記憶體 共享記憶體也是通過核心來完成 命令 ipcs m p s 共享記憶體的工作機制如下所示 首先linux系統執行的每乙個程式,都是乙個程...