管道技術是Linux的一種基本的進程間通信技術。在本文中,我們將為讀者介紹管道技術的模型,匿名管道和命名管道技術的定義和區別,以及這兩種管道的創建方法。同時,闡述如何在應用程序和命令行中通過管道進行通信的詳細方法。
一、管道技術模型
管道技術是Linux操作系統中歷來已久的一種進程間通信機制。所有的管道技術,無論是半雙工的匿名管道,還是命名管道,它們都是利用FIFO排隊模型來指揮進程間的通信。對于管道,我們可以形象地把它們當作是連接兩個實體的一個單向連接器。例如,請看下面的命令:
該命令首先創建兩個進程,一個對應于ls –1,另一個對應于wc –l。然后,把第一個進程的標準輸出設為第二個進程的標準輸入(如圖1所示)。它的作用是計算當前目錄下的文件數量。
圖1:管道示意圖
如上圖所示,前面的例子實際上就是在兩個命令之間建立了一根管道(有時我們也將之稱為命令的流水線操作)。第一個命令ls執行后產生的輸出作為了第二個命 令wc的輸入。這是一個半雙工通信,因為通信是單向的。兩個命令之間的連接的具體工作,是由內核來完成的。下面我們將會看到,除了命令之外,應用程序也可 以使用管道進行連接。
二、信號和消息的區別
我們知道,進程間的信號通信機制在傳遞信息時是以信號為載體的,但管道通信機制的信息載體是消息。那么信號和消息之間的區別在哪里呢?
首先,在數據內容方面,信號只是一些預定義的代碼,用于表示系統發生的某一狀況;消息則為一組連續語句或符號,不過量也不會太大。在作用方面,信號擔任進程間少量信息的傳送,一般為內核程序用來通知用戶進程一些異常情況的發生;消息則用于進程間交換彼此的數據。
在 發送時機方面,信號可以在任何時候發送;信息則不可以在任何時刻發送。在發送者方面,信號不能確定發送者是誰;信息則知道發送者是誰。在發送對象方面,信 號是發給某個進程;消息則是發給消息隊列。在處理方式上,信號可以不予理會;消息則是必須處理的。在數據傳輸效率方面,信號不適合進大量的信息傳輸,因為 它的效率不高;消息雖然不適合大量的數據傳送,但它的效率比信號強,因此適于中等數量的數據傳送。
三、管道和命名管道的區別
我們知道,命名管道和管道都可以在進程間傳送消息,但它們也是有區別的。
管道技術只能用于連接具有共同祖先的進程,例如父子進程間的通信,它無法實現不同用戶的進程間的信息共享。再者,管道不能常設,當訪問管道的進程終止時,管道也就撤銷。這些限制給它的使用帶來不少限制,但是命名管道卻克服了這些限制。
命名管道也稱為FIFO,是一種永久性的機構。FIFO文件也具有文件名、文件長度、訪問許可權等屬性,它也能像其它Linux文件那樣被打開、關閉和刪除,所以任何進程都能找到它。換句話說,即使是不同祖先的進程,也可以利用命名管道進行通信。
如果想要全雙工通信,那最好使用Sockets API。下面我們分別介紹這兩種管道,然后詳細說明用來進行管道編程的編程接口和系統級命令。
四、管道編程技術
在程序中利用管道進行通信時,根據通信主體大體可以分為兩種情況:一種是具有共同祖先的進程間的通信,比較簡單;另一種是任意進程間通信,相對較為復雜。下面我們先從較為簡單的進程內通信開始介紹。
1. 具有共同祖先的進程間通信管道編程
為了了解管道編程技術,我們先舉一個例子。在這個例中,我們將在進程中新建一個管道,然后向它寫入一個消息,管道讀取消息后將其發出。代碼如下所示:
示例代碼1:管道程序示例
原文轉自:http://yp.oss.org.cn/blog/show_resource.php?resource_id=598