1. 程式人生 > >管道、訊息佇列、共享記憶體、訊號量的特點

管道、訊息佇列、共享記憶體、訊號量的特點

在之前我們已經瞭解過了程序間通訊的幾種方式:管道訊息佇列共享記憶體以及訊號量。今天我們就來總結一下這幾種方式的各自的特點分別是什麼,和他們相應的應用場景。也是對於這個知識點的一個複習和鞏固。

Q1:為什麼要有程序間通訊???

A1:
1、為了傳輸資料:一個程序需要將它的資料傳送給另外一個程序;
2、為了共享資源:多個程序之間有時需要共享同樣的一份資源;
3、為了通知事件:一個程序需要向另一個程序或者程序組傳送訊息通知他們發生了某些事件(比如:一個程序退出時需要通知他的父程序);
4、為了實現程序控制:有些程序希望控制另一個程序的執行,此時控制程序希望能夠攔截另外一個程序的所有陷入和異常,並能夠及時知道他的狀態改變。

Q2:程序間通訊的本質是什麼???

A2:
不同的兩個程序之間,他們的程序地址空間自然也是相互獨立的,而程序間通訊就是為了讓兩個程序之間能夠共同的知曉某一份資料、訊息等這些資源。一句話就是:程序間通訊的本質就是:讓不同的程序可以看到同一份資源。

下面來總結一下,幾種通訊方式的特點:
管道

把從一個程序連線到另一個程序的一個數據流稱為一個管道。
管道又分為命名管道和匿名管道
匿名管道:只允許具有親緣關係的程序間通訊
命名管道:允許不想管的程序之間進行通訊

特點:
1:只能用於具有共同祖先的程序(具有親緣關係的程序)之間進行通訊;通常情況下,一個管道有一個程序建立,然後該程序呼叫fork,此後父程序與子程序就可應用該管道。
2:管道提供流式服務(面向位元組流)。
3:一般而言,程序退出,管道釋放,所以管道的生命週期隨程序。


4:核心會對管道操作進行同步與互斥。
5:管道是半雙工的,資料只能向一個方向流動,需要雙方通訊時,要建立起兩個管道。

應用場景:
1、用於shell中(如:who | wc -l)
2、用於具有親緣關係的程序間通訊

命名管道和匿名管道的唯一區別就在於二者建立和開啟的方式不同。
匿名管道的建立和開啟由pipe函式完成
而命名管道有mkfifo函式建立,開啟需要用open

#include<unistd.h>
//建立一個無名管道
int pipe(int fd[2]);
//引數:fd為檔案描述符組,其中fd[0]表示讀端,fd[1]表示寫端
//返回值:成功返回0,失敗返回錯誤碼 int mkfifo(const char *filename,mode_t mode); //如: int main(int argc,char *argv[]) { mkfifo("p",0644); return 0; } //也可以直接在命令列上建立 mkfifo filename

訊息佇列
訊息佇列提供了一種在兩個不相關的程序之間傳遞資料的簡單高效的方法。

特點:
1、它提供有格式的位元組流,減少了開發人員的工作量;訊息具有型別(system V)或優先順序(posix)。其他方式都沒有這些優點。
2、具備同步機制。
3、生命週期隨核心。
4、訊息佇列允許一個或多個程序向它寫入或者讀取訊息。
5、與無名管道、命名管道一樣,從訊息佇列中讀出訊息,訊息佇列中對應的資料都會被刪除。
6、每個訊息佇列都有訊息佇列識別符號,訊息佇列的識別符號在整個系統中是唯一的。
訊息佇列是訊息的連結串列,存放在記憶體中,由核心維護。只有核心重啟或人工刪除訊息佇列時,該訊息佇列才會被刪除。若不人工刪除訊息佇列,訊息佇列會一直存在於系統中。

共享記憶體
使得多個程序可以訪問同一塊記憶體空間,是最快的可用IPC形式。

特點:
1、共享記憶體沒有提供任何的保護機制
2、是臨界資源
3、沒有同步互斥機制
4、生命週期隨核心(同訊息佇列)

訊號量
主要作為程序間以及同一程序不同執行緒之間的同步手段。

特點:
1、本質是一個計數器,記憶體中有多少個臨界資源,訊號量的數字就是多少。
2、訊號量基於作業系統的 PV 操作,程式對訊號量的操作都是原子操作
3、訊號量用於程序間同步,若要在程序間傳遞資料需要結合共享記憶體。

優缺點總結:

1.管道:速度慢,容量有限,只能用於具有親緣關係的程序間通訊。
2.FIFO:任何程序間都能通訊,但速度慢。
3.訊息佇列:容量受到系統限制。
4.訊號量:不能傳遞複雜訊息,只能用來同步。
5.共享記憶體區:能夠很容易控制容量,速度快,但要保持同步。