我們在linux訊號基礎中已經說明,訊號可以看作一種粗糙的程序間通訊(ipc, interprocess communication)的方式,用以向程序封閉的記憶體空間傳遞資訊。為了讓程序間傳遞更多的資訊量,我們需要其他的程序間通訊方式。這些程序間通訊方式可以分為兩種:
乙個原始的ipc方式是所有的程序通過乙個檔案交流。比如我在紙(檔案)上寫下我的名字和年紀。另乙個人讀這張紙,會知道我的名字和年紀。他也可以在同一張紙上寫下他的資訊,而當我讀這張紙的話,同樣也可以知道別人的資訊。但是,由於硬碟讀寫比較慢,所以這個方式效率很低。那麼,我們是否可以將這張紙放入記憶體中以提高讀寫速度呢?
在linux文字流中,我們已經講解了如何在shell中使用管道連線多個程序。同樣,許多程式語言中,也有一些命令用以實現類似的機制,比如在python子程序中使用popen和pipe,在c語言中也有popen庫函式來實現管道 (shell中的管道就是根據此編寫的)。管道是由核心管理的乙個緩衝區(buffer),相當於我們放入記憶體中的乙個紙條。管道的一端連線乙個程序的輸出。這個程序會向管道中放入資訊。管道的另一端連線乙個程序的輸入,這個程序取出被放入管道的資訊。乙個緩衝區不需要很大,它被設計成為環形的資料結構,以便管道可以被迴圈利用。當管道中沒有資訊的話,從管道中讀取的程序會等待,直到另一端的程序放入資訊。當管道被放滿資訊的時候,嘗試放入資訊的程序會等待,直到另一端的程序取出資訊。當兩個程序都終結的時候,管道也自動消失。
從原理上,管道利用fork機制建立(參考linux程序基礎和linux從程式到程序),從而讓兩個程序可以連線到同乙個pipe上。最開始的時候,上面的兩個箭頭都連線在同乙個程序process 1上(連線在process 1上的兩個箭頭)。當fork複製程序的時候,會將這兩個連線也複製到新的程序(process 2)。隨後,每個程序關閉自己不需要的乙個連線 (兩個黑色的箭頭被關閉; process 1關閉從pipe來的輸入連線,process 2關閉輸出到pipe的連線),這樣,剩下的紅色連線就構成了如上圖的pipe。
由於基於fork機制,所以管道只能用於父程序和子程序之間,或者擁有相同祖先的兩個子程序之間 (有親緣關係的程序之間)。為了解決這一問題,linux提供了fifo方式連線程序。fifo又叫做命名管道(named pipe)。
fifo (first in, first out)為一種特殊的檔案型別,它在檔案系統中有對應的路徑。當乙個程序以讀(r)的方式開啟該檔案,而另乙個程序以寫(w)的方式開啟該檔案,那麼核心就會在這兩個程序之間建立管道,所以fifo實際上也由核心管理,不與硬碟打交道。之所以叫fifo,是因為管道本質上是乙個先進先出的佇列資料結構,最早放入的資料被最先讀出來(好像是傳送帶,一頭放貨,一頭取貨),從而保證資訊交流的順序。fifo只是借用了檔案系統(file system, 參考linux檔案管理背景知識)來為管道命名。寫模式的程序向fifo檔案中寫入,而讀模式的程序從fifo檔案中讀出。當刪除fifo檔案時,管道連線也隨之消失。fifo的好處在於我們可以通過檔案的路徑來識別管道,從而讓沒有親緣關係的程序之間建立連線。
這幾種傳統ipc實際上有很悠久的歷史,所以其實現方式也並不完善 (比如說我們需要某個程序負責刪除建立的ipc)。乙個共同的特徵是它們並不使用檔案操作的api。對於任何一種ipc來說,你都可以建立多個連線,並使用鍵值(key)作為識別的方式。我們可以在乙個程序中中通過鍵值來使用的想要那乙個連線 (比如多個訊息佇列,而我們選擇使用其中的乙個)。鍵值可以通過某種ipc方式在程序間傳遞(比如說我們上面說的pipe,fifo或者寫入檔案),也可以在程式設計的時候內置於程式中。
在幾個程序共享鍵值的情況下,這些傳統ipc非常類似於多執行緒共享資源的方式(參看linux多執行緒與同步):
訊息佇列(message queue)與pipe相類似。它也是建立乙個佇列,先放入佇列的訊息被最先取出。不同的是,訊息佇列允許多個程序放入訊息,也允許多個程序取出訊息。每個訊息可以帶有乙個整數識別符(message_type)。你可以通過識別符對訊息分類 (極端的情況是將每個訊息設定乙個不同的識別符)。某個程序從佇列中取出訊息的時候,可以按照先進先出的順序取出,也可以只取出符合某個識別符的訊息(有多個這樣的訊息時,同樣按照先進先出的順序取出)。訊息佇列與pipe的另乙個不同在於它並不使用檔案api。最後,乙個佇列不會自動消失,它會一直存在於核心中,直到某個程序刪除該佇列。
多程序協作可以幫助我們充分利用多核和網路時代帶來的優勢。多程序可以有效解決計算瓶頸的問題。網際網路通訊實際上也是乙個程序間通訊的問題,只不過這多個程序分布於不同的電腦上。網路連線是通過socket實現的。由於socket內容龐大,所以我們不在這裡深入。乙個小小的註解是,socket也可以用於計算機內部程序間的通訊。
pipe, fifo
semaphore, message queue, shared memory; key
Linux程序間通訊
程序間通訊 ipc interprocess communication 基本機制 訊號 管道及命名管道 訊息佇列 共享主存 訊號量 套接字。訊號 全稱軟中斷訊號,是在軟體層次上對中斷機制的一種模擬,它也是程序間通訊機制中唯一的非同步通訊機制。linux訊號處理函式可分為訊號安裝函式 訊號傳送函式和...
Linux程序間通訊
謝謝nonoob糾錯 我們在linux訊號基礎中已經說明,訊號可以看作一種粗糙的程序間通訊 ipc,interprocess communication 的方式,用以向程序封閉的記憶體空間傳遞資訊。為了讓程序間傳遞更多的資訊量,我們需要其他的程序間通訊方式。這些程序間通訊方式可以分為兩種 1.管道與...
Linux程序間通訊
謝謝nonoob糾錯 我們在linux訊號基礎中已經說明,訊號可以看作一種粗糙的程序間通訊 ipc,interprocess communication 的方式,用以向程序封閉的記憶體空間傳遞資訊。為了讓程序間傳遞更多的資訊量,我們需要其他的程序間通訊方式。這些程序間通訊方式可以分為兩種 1.管道與...