Linux程序間通訊總結

2021-08-31 16:30:42 字數 3949 閱讀 9681

目錄訊號

管道命名管道

system v ipc 組成

識別符號ftok函式

結構定義 特點

訊息佇列

訊號量共享記憶體

套接字linux下的程序間通訊(interprocess communication,ipc)方式基本上是從unix繼承而來的。對unix發展做出重大貢獻的兩個實驗室:at&t的貝爾實驗室、bsd在ipc方面的側重點有所不同。前者對unix早期的ipc手段進行了系統的改進和擴充,形成了「system v ipc」,通訊程序侷限在單個計算機內;後者則跳過了該限制,形成了基於套接字(socket)的程序間通訊機制。linux則把兩者都繼承了下來,加上作業系統早期的訊號、管道、命名管道,構成了linux豐富的ipc方式。

下面先介紹幾個作業系統最早使用的ipc機制:

訊號又稱軟體中斷,本質是對硬體中斷的模擬,是作業系統最原始的非同步通訊機制,linux提供了一系列函式讓使用者註冊訊號,自定義中斷處理例程,傳送訊號等,程序間通過訊號進行同步。但訊號存在系統開銷大、傳送資訊量有限等問題,所以實際應用中,訊號機制常常用於程序間的事件通知,而不應用於複雜的互動操作。

關於中斷概念及中斷處理:

關於linux訊號機制:

管道也稱匿名管道,相當於一塊環形緩衝區,它只存在於記憶體中,程序通過對管道的讀寫來實現資料互動。管道有單工的也有半雙工的,單工管道只能單向傳輸,半雙工管道可以實現雙向傳輸,但同一時刻只允許乙個方向的傳輸。管道只存在於記憶體中的作業系統核心部分,因此只能在有親屬關係(父子程序、兄弟程序)的程序間使用。

linux管道程式設計:

命名管道相較於管道去除了只能在有親屬關係的程序間使用的限制,因為命名管道是乙個實實在在的檔案,存在於檔案系統中,因此任何有許可權訪問該命名管道的程序都能使用命名管道進行資料互動。

linux命名管道程式設計:

需要注意的是,posix大體繼承了system v ipc,可以說posix只是做了統一標準化的工作,而除了在函式命名格式上有所不同外,可以將posix的ipc視為system v ipc看待。linux同時支援這兩種標準。

system v ipc由以下三種ipc物件組成,三者都有著類似的結構(下文詳述):

訊息佇列:

訊號量:

共享記憶體:

system v ipc由訊息佇列、訊號量和共享記憶體三種ipc方式組成,這三種ipc通訊方式在程式設計介面和內部實現上都非常類似,例如都採用類似的控制函式、ipc_perm結構等。

linux核心提供了相應的標頭檔案用於實現system v ipc,三種不同的通訊方式分別對應不同的標頭檔案和動作操作函式,如下表所示:

system v ipc

實現方式

頭檔案建立或開啟ipc物件

ipc物件控制函式

ipc物件操作函式

訊息佇列

msgget

msgctl

msgsnd

msgcv

訊號量semget

semctl

semop

共享記憶體

shmget

shmctl

shmat

shmdt

每乙個system v ipc的結構(訊息佇列、訊號量和共享記憶體)都對應了乙個識別符號(id),它是乙個非負整數,當乙個ipc結構被建立時,和該結構相關的識別符號會自動加1並賦予新建立的ipc結構,這個非負整數溢位時會回滾到0重新開始。

識別符號的唯一性侷限於結構型別內。假設某個訊息佇列的識別符號為1,則這個識別符號在所有訊息佇列中是唯一的,但有可能存在識別符號為1的訊號量或共享記憶體。

三種ipc結構的建立函式都有乙個key_t型別的引數key,使用者程序將這個引數值傳遞給核心,由核心轉換為識別符號。

linux提供了ftok函式用於將乙個路徑和專案id轉換為關鍵字,其標準呼叫格式說明如下:

#include #incldue key_t ftok(const char *pathname, int proj_id);
其中第乙個引數pathname必須是乙個存在的、可以訪問的檔案路徑名,而第二個引數proj_id則只有低8位有效(如果低8位為0,返回的是乙個隨機結果)。函式呼叫成功則返回key_t型別的關鍵字供程序建立ipc物件使用,否則返回-1。

需要注意的是,ftok函式返回的關鍵字是根據檔案的物理索引(inode) 確定的,因此路徑名相同並不意味著frok函式產生的關鍵字也會相同。

雖然使用ipc機制的程序可以直接利用諸如123這樣的整數作為關鍵字,但它們要在程式編碼上保持一致,並且這麼做還有乙個缺點:其他程序也可能使用這個整數作為另外的ipc資源的關鍵字,這種情況下可能導致混亂。因此最好利用ftok函式來生成關鍵字。

每乙個ipc物件都有乙個ipc_perm結構與之對應,這個結構中記錄了物件的一些資訊,如所有者、建立者和許可權等:

struct ipc_perm

;

ipc_perm結構中的mode記錄了ipc物件的訪問許可權,它與檔案的訪問許可權類似,同樣分為使用者、組使用者和其他使用者三類。但是這些許可權中沒有可執行許可權。

ipc物件的訪問許可權 許可權

訊息佇列

訊號量共享記憶體

使用者可讀

msg_r

sem_r

shm_r

可寫msgw

組使用者可讀

msg_r >> 3

sem_r >> 3

shm_r >> 3

可寫msg_w >> 3

sem_a >> 3

shm_w >> 3

其他使用者

可讀msg_r >> 6

sem_r >> 6

shm_r >> 6

可寫msg_w >> 6

sem_a >> 6

shm_w >> 6

mode位還經常和ipc_create、ipc_excl兩種標誌位進行位或運算,以完成對ipc物件的建立管理。

#include #define ipc_create 01000    /* create key if key does not exist. */

#define ipc_excl 02000 /* fail if key exists. */

linux核心提供了相應的函式來建立乙個新的或者訪問乙個已經存在的ipc物件,對其建立或者訪問的規則如下:

·指定key為ipc_private,作業系統保證建立乙個唯一的ipc物件。

·設定flag引數的ipc_create位,但不設定它的ipc_excl位時,如果所指定key的ipc物件不存在,就建立乙個新的物件,否則返回該物件。

·同時設定flag引數的ipc_create和ipc_excl時,如果所指定key的ipc物件不存在,就建立乙個新的物件,否則返回乙個eexist錯誤。

system v ipc機制具有以下幾個特點:

·ipc結構存在於linux核心空間,它沒有計數機制,也不會自我刪除,停止使用的ipc結構會一直保留在系統核心空間中,除非主動刪除。

·ipc結構不能再檔案系統中公開訪問,不能使用檔案操作的函式來對這些結構進行操作。

·ipc結構沒有檔案描述符,所以不能對其使用i/o多路復用seclect和epoll,也不能在檔案或者裝置i/o中使用ipc結構,還不能一次性使用多個ipc結構。

訊息佇列(message queue)由鍊錶實現,訊息不一定要按照先進先出的形式來讀寫,因此可以實現訊息的隨機查詢。最重要的是,訊息佇列可以按格式讀寫資料,而管道和有名管道只能處理無格式位元組流。

訊息佇列程式設計:

訊號量程式設計:

共享記憶體就是將一塊記憶體對映到其他程序的虛擬位址空間中,這段共享記憶體由乙個程序建立,但多個程序都可以訪問。共享記憶體是最快的ipc方式,它是針對其他程序間通訊方式執行效率低而專門設計的。它往往與其他通訊機制,如訊號量,配合使用,來實現程序間的同步和通訊。

共享記憶體程式設計:

套接字(socket)最早是由bsd為實現多計算機之間的通訊而開發的,在計算機網路通訊中套接字起著非常重要的作用。

套接字程式設計(tcp):

Linux 程序間通訊總結

pipe管道 屬於匿名管道,這個通訊管道通過pipe int filedes 2 系統呼叫而建立,filedes 0 代表讀端,filedes 1 代表寫端,fifo 又叫做命名管道,由於fifo在檔案基礎上為管道提供了命名服務,fifo通過乙個真實的檔名來訪問 system v ipc 共享記憶體...

Linux程序間通訊方式總結

linux系統中的程序間通訊方式主要以下幾種 同一主機上的程序通訊方式 unix程序間通訊方式 包括管道 pipe 有名管道 fifo 和訊號 signal system v程序通訊方式 包括訊號量 semaphore 訊息佇列 message queue 和共享記憶體 shared memory ...

linux 程序間通訊方式總結

對linux 程序通訊的一點簡單總結,主要包括 管道通訊,還有 system v,posix 標準的 訊息佇列,訊號量,共享記憶體方式。基於管道的通訊主要包括有名管道,和無名管道,所謂的有名管道,就是建立的時候會帶有具體的標識,以便於確認對誰操作,而無名管道是建立沒有名字的管道,在於用的時候是否需要...