linux系統IPC通訊 共享記憶體

2021-09-02 19:52:12 字數 3223 閱讀 9978

很久以前就想研究一下核心原始碼,今天開始看看共享記憶體是如何實現的.

以前就了解幾個函式.

#include #include int shmget(key_t key, size_t size, int shm***); 

void *shmat(int shm_id, const void *shm_addr, int shm***);

int shmdt(const void *shm_addr); int shmctl(int shm_id, int cmd, struct shmid_ds *buf);

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

shmget函式

該函式用來建立共享記憶體:

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

key:標識共享記憶體的鍵值: 0/ipc_private。 當key的取值為ipc_private,則函式shmget()將建立一塊新的共享記憶體;如果key的取值為0,而引數shm***中設定了ipc_private這個標誌,則同樣將建立一塊新的共享記憶體。

在ipc(interprocess communication)的通訊模式下,不管是使用訊息佇列還是共享記憶體,甚至是訊號量,每個ipc的物件(object)都有唯一的名字,稱為「鍵」(key)。通過「鍵」,程序能夠識別所用的物件。「鍵」與ipc物件的關係就如同檔名稱之於檔案,通過檔名,程序能夠讀寫檔案內的資料,甚至多個程序能夠共用乙個檔案。而在ipc的通訊模式下,通過「鍵」的使用也使得乙個ipc物件能為多個程序所共用。

linux系統中的所有表示system v中ipc物件的資料結構都包括乙個ipc_perm結構,其中包含有ipc物件的鍵值,該鍵用於查詢system v中ipc物件的引用識別符號。如果不使用「鍵」,程序將無法訪問ipc物件,因為ipc物件並不存在於程序本身使用的記憶體中。

通常,都希望自己的程式能和其他的程式預先約定乙個唯一的鍵值,但實際上並不是總可能的成行的,因為自己的程式無法為一塊共享記憶體選擇乙個鍵值。因此,在此把key設為ipc_private,這樣,作業系統將忽略鍵,建立乙個新的共享記憶體,指定乙個鍵值,然後返回這塊共享記憶體ipc識別符號id。而將這個新的共享記憶體的識別符號id告訴其他程序可以在建立共享記憶體後通過派生子程序,或寫入檔案或管道來實現。

size: 是要建立共享記憶體的長度。所有的記憶體分配操作都是以頁為單位的。所以如果一段程序只申請一塊只有乙個位元組的記憶體,記憶體也會分配整整一頁(在i386機器中一頁的預設大小pace_size=4096位元組)這樣,新建立的共享記憶體的大小實際上是從size這個引數調整而來的頁面大小。即如果size為1至4096,則實際申請到的共享記憶體大小為4k(一頁);4097到8192,則實際申請到的共享記憶體大小為8k(兩頁),依此類推。

shm***:主要和一些標誌有關。其中有效的包括ipc_creat和ipc_excl,它們的功能與open()的o_creat和o_excl相當。

ipc_creat 如果共享記憶體不存在,則建立乙個共享記憶體,否則開啟操作。

ipc_excl 只有在共享記憶體不存在的時候,新的共享記憶體才建立,否則就產生錯誤。

如果單獨使用ipc_creat,shmget()函式要麼返回乙個已經存在的共享記憶體的操作符,要麼返回乙個新建的共享記憶體的識別符號。如果將ipc_creat和ipc_excl標誌一起使用,shmget()將返回乙個新建的共享記憶體的識別符號;如果該共享記憶體已存在,或者返回-1。ipc_exel標誌本身並沒有太大的意義,但是和ipc_creat標誌一起使用可以用來保證所得的物件是新建的,而不是開啟已有的物件。對於使用者的讀取和寫入許可指定shm_r和shm_w,(shm_r>3)和(shm_w>3)是一組讀取和寫入許可,而(shm_r>6)和(shm_w>6)是全域性讀取和寫入許可。

需要注意的是,使用引數要加上 | 0666 作為校驗,在有些linux系統中,如果不加此校驗,則不能順利獲取共享空間的值(如ubuntu)。此外,有兩個常用引數,一般要同時出現,他們是:s_irush | s_iwusr 。由於這兩個引數非常常用,程式設計師一般做這樣的操作

#define perm s_irusr | s_iwusr | ipc_creat

這樣一來,第三個引數就可以直接用perm來表示了!

返回值成功返回共享記憶體的識別符號;不成功返回-1,errno儲存錯誤原因。

einval        引數size小於shmmin或大於shmmax。

eexist 預建立key所致的共享記憶體,但已經存在。

eidrm 引數key所致的共享記憶體已經刪除。

enospc 超過了系統允許建立的共享記憶體的最大值(shmall )。

enoent 引數key所指的共享記憶體不存在,引數shm***也未設ipc_creat位。

eacces 沒有許可權。

enomem 核心記憶體不足。note: 許可權標誌對共享記憶體非常有用,因為它允許乙個程序建立的共享內

存可以被共享記憶體的建立者所擁有的程序寫入,同時其它使用者建立的程序只能讀取共享記憶體。

我們可以利用這個功能來提供一種有效的對資料進行唯讀訪問的方法,通過將資料放共享記憶體並設定它的許可權,就可以避免資料被其他使用者修改。

建立成功,則返回乙個非負整數,即共享記憶體標識;如果失敗,則返回-1.

shmget這個函式要呼叫

shm.c

syscall_define3(shmget, key_t, key, size_t, size, int, shm***)

util.c

int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,

struct ipc_ops *ops, struct ipc_params *params)

static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, struct ipc_ops *ops, struct ipc_params *params)

up_write(&ids->rw_mutex);

}shmid_ds資料結構表示每個新建的共享記憶體。當shmget()建立了一塊新的共享記憶體後,返回乙個可以用於引用該共享記憶體的shmid_ds資料結構的識別符號。

include/linux/shm.h

struct shmid_ds ;

**太多了,其他的自己看吧,

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

兩個不同程序a b共享記憶體的意思是,同一塊物理記憶體被對映到程序a b各自的程序位址空間。程序a可以即時看到程序b對共享記憶體中資料的更新,反之亦然。由於多個程序共享同一塊記憶體區域,必然需要某種同步機制,互斥鎖和訊號量都可以。ipcs m 檢視共享記憶體 ipcrm m shmid 刪除共享記憶...

Linux程序間通訊 IPC 共享記憶體

共享記憶體是基於虛擬記憶體的機制,在程序的位址空間中,共享區域的虛擬頁通過核心中的頁表對映到實際的物理頁中,當多個程序都對映到同一塊物理頁,那麼它們訪問的就是同一片物理記憶體,即共享記憶體。此時基於同一片記憶體,程序間進行資訊傳輸的速度將非常快,每個程序相當於訪問自己位址空間內的記憶體資料。關鍵函式...

IPC通訊之共享記憶體

共享記憶體就是使得多個程序可以訪問同一塊記憶體空間,是最快的可用 ipc形式。是針對其他通訊機制執行效率較低而設計的。往往與其它通訊機制,如訊號量結合使用,來達到程序間的同步及互斥。我們通過一張圖來表示這個關係 共享記憶體和訊息佇列,訊號量一樣都屬於xsi ipc。核心都為他們維護了一套資料結構 同...