Linux程序間通訊 共享記憶體

2021-08-02 15:06:03 字數 3379 閱讀 4075

一、共享記憶體

1、共享記憶體的概念:

顧名思義,共享記憶體就是允許兩個不相關的程序訪問同乙個邏輯記憶體。共享記憶體是在兩個正在執行的程序之間共享和傳遞資料的一種非常有效的方式。不同程序之間共享的記憶體通常安排為同一段物理記憶體。程序可以將同一段共享記憶體連線到它們自己的位址空間中,所有程序都可以訪問共享記憶體中的位址,就好像它們是由用c語言函式malloc分配的記憶體一樣。而如果某個程序向共享記憶體寫入資料,所做的改動將立即影響到可以訪問同一段共享記憶體的任何其他程序。共享記憶體並未提供同步機制,也就是說,在第乙個程序結束對共享記憶體的寫操作之前,並無自動機制可以阻止第二個程序開始對它進行讀取。所以我們通常需要用其他的機制來同步對共享記憶體的訪問。

2、共享記憶體的實現原理:

共享記憶體的實現(使用對映機制):兩個不同程序共享同一塊物理記憶體,達到訪問同乙份資源的目的 :

共享記憶體是所有程序間通訊速度最快的一種方式,省去了資料的copy在訊息佇列中就是server和client都讀取了對方的資料並拷貝下來,因此有兩次拷貝。但是共享記憶體優缺點:他自身不提供同步於互斥機制(可以通過訊號量來實現),一般申請記憶體,都是按照一頁的大小,避免記憶體碎片(4k為一頁)如果申請到的記憶體不夠一頁那麼作業系統自動會進行向上調整,把它申請成為一頁,一頁半就是兩頁。

共享記憶體的特點:生命週期隨核心 。

二、共享記憶體的獲得

共享記憶體由shmget、shmat、shmdt、shmctl四個函式組成。

1、shmget函式:

該函式用來建立共享記憶體,它的原型為:

int shmget(key_t key, size_t size, int shm***);
key_t key,與訊號量的semget函式一樣,程式需要提供乙個引數key(非0整數),它有效地為共享記憶體段命名,shmget函式成功時返回乙個與key相關的共享記憶體識別符號(非負整數),用於後續的共享記憶體函式。呼叫失敗返回-1。

size_t size ,size以位元組為單位指定需要共享的記憶體容量。

int shm***,shm***是許可權標誌,它的作用與open函式的mode引數一樣,如果要想在key標識的共享記憶體不存在時,建立它的話,可以與ipc_creat做或操作。

2、shmat函式:

void *shmat(int shm_id, const void *shm_addr, int shm***);
shm_id :代表共享記憶體的標識

shm_addr: 指定共享記憶體出現在程序記憶體位址的什麼位置,直接指定為null讓核心自己決定乙個合適的位址位置

shm***:可直接設定為0

3、shmdt函式:

該函式用於將共享記憶體從當前程序中分離。注意,將共享記憶體分離並不是刪除它,只是使該共享記憶體對當前程序不再可用。它的原型如下:

int shmdt(const void *shmaddr);
引數shmaddr是shmat函式返回的位址指標,呼叫成功時返回0,失敗時返回-1。

4、shmctl函式:

與訊號量的semctl函式一樣,用來控制共享記憶體,它的原型如下:

int shmctl(int shm_id, int command, struct shmid_ds *buf);
shm_id是shmget函式返回的共享記憶體識別符號。

command是要採取的操作,它可以取下面的三個值 :

ipc_stat:把shmid_ds結構中的資料設定為共享記憶體的當前關聯值,即用共享記憶體的當前關聯值覆蓋shmid_ds的值。

ipc_set:如果程序有足夠的許可權,就把共享記憶體的當前關聯值設定為shmid_ds結構中給出的值

ipc_rmid:刪除共享記憶體段

buf是乙個結構指標,它指向共享記憶體模式和訪問許可權的結構。

shmid_ds結構至少包括以下成員:  

struct shmid_ds  

;

三、實現基於共享記憶體的通訊

**塊:

1、shm.h

#ifndef _shm_h_

#define _shm_h_

#define pathname "."

#define proj_id 0x6666

#include#include #include #include #include #include int getshm();

int createshm();

char* shmat(int shmid);

int shmdt(char*add);

int comshm();

#endif

2、shm.c

#include"shm.h"

int comshm(int flag)

int shmid=shmget(key,4096,flag|0666);

if(shmid<0)

return shmid;

}int createshm()

int getshm()

int destroyshm(int shmid)

return 0;

}char* shmat(int shmid)

int shmdt(char*add)

return 0;

}

3、test.c

#include"shm.h"

int main()

buf[i]=0;

shmdt(buf);

}else

return 0;

}

4、程式執行結果:

5、ipc 命令:

ipcs -m 檢視共享記憶體

ipcrm -m shmid 刪除共享記憶體

6、使用共享記憶體的優缺點

1)優點:我們可以看到使用共享記憶體進行程序間的通訊真的是非常方便,而且函式的介面也簡單,資料的共享還使程序間的資料不用傳送,而是直接訪問記憶體,也加快了程式的效率。同時,它也不像匿名管道那樣要求通訊的程序有一定的父子關係。共享記憶體相比其他幾種方式有著更方便的資料控制能力,資料在讀寫過程中會更透明。當成功匯入一塊共享記憶體後,它只是相當於乙個字串指標來指向一塊記憶體,在當前程序下使用者可以隨意的訪問。

2)缺點:共享記憶體沒有提供同步的機制資料寫入程序或資料讀出程序中,需要附加的資料結構控制。這使得我們在使用共享記憶體進行程序間通訊時,往往要借助其他的手段來進行程序間的同步工作。

Linux程序間通訊 共享記憶體

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

Linux程序間共享記憶體通訊

使用共享記憶體基本分四個步驟 獲得共享記憶體 shmget 對映共享記憶體shmat 解除對映shmdt 刪除共享記憶體shmctl 於是自己在網上找來了乙個例子看了下,並且用虛擬機器單獨跑了下共享記憶體的經典例程看了下,才知道了自己的問題出現 了 發現有時候只要自己親自將程式一步一步的去測,才知道...

Linux程序間通訊 共享記憶體

之前提到了程序間通訊的管道,訊息佇列,訊號量,然後其中訊號量是pv操作,操控的是乙個共享資源。在我們提到的ipc模組中,訊息佇列針對的是資料單元的資訊傳送,管道不屬於system v ipc的部分,所以按照乙個作業系統的整體來說,他應該也有著乙個關於位元組流的訊息傳輸,並且要比之前都要快,還要跟我們...