使用系统调用pipe建立一条管道线_【Linux系统】Linux进程间通信
作者:Vamei
出處:http://www.cnblogs.com/vamei
我們在Linux信號基礎(chǔ)中已經(jīng)說明,信號可以看作一種粗糙的進(jìn)程間通信(IPC, interprocess communication)的方式,用以向進(jìn)程封閉的內(nèi)存空間傳遞信息。為了讓進(jìn)程間傳遞更多的信息量,我們需要其他的進(jìn)程間通信方式。這些進(jìn)程間通信方式可以分為兩種:管道機(jī)制:可以使用管道將一個進(jìn)程的輸出和另一個進(jìn)程的輸入連接起來,從而利用文件操作API來管理進(jìn)程間通信。在shell中,我們經(jīng)常利用管道將多個進(jìn)程連接在一起,從而讓各個進(jìn)程協(xié)作,實(shí)現(xiàn)復(fù)雜的功能。
傳統(tǒng)IPC:主要是指消息隊(duì)列(message queue),信號量(semaphore),共享內(nèi)存(shared memory)。這些IPC的特點(diǎn)是允許多進(jìn)程之間共享資源,這與多線程共享heap和global data相類似。由于多進(jìn)程任務(wù)具有并發(fā)性 (每個進(jìn)程包含一個進(jìn)程,多個進(jìn)程的話就有多個線程),所以在共享資源的時(shí)候也必須解決同步的問題 (參考Linux多線程與同步)。?
管道與FIFO文件一個原始的IPC方式是所有的進(jìn)程通過一個文件交流。比如我在紙(文件)上寫下我的名字和年紀(jì)。另一個人讀這張紙,會知道我的名字和年紀(jì)。他也可以在同一張紙上寫下他的信息,而當(dāng)我讀這張紙的話,同樣也可以知道別人的信息。但是,由于硬盤讀寫比較慢,所以這個方式效率很低。那么,我們是否可以將這張紙放入內(nèi)存中以提高讀寫速度呢?在Linux文本流中,我們已經(jīng)講解了如何在shell中使用管道連接多個進(jìn)程。同樣,許多編程語言中,也有一些命令用以實(shí)現(xiàn)類似的機(jī)制,比如在Python子進(jìn)程中使用Popen和PIPE,在C語言中也有popen庫函數(shù)來實(shí)現(xiàn)管道 (shell中的管道就是根據(jù)此編寫的)。
管道是由內(nèi)核管理的一個緩沖區(qū)(buffer),相當(dāng)于我們放入內(nèi)存中的一個紙條。管道的一端連接一個進(jìn)程的輸出。這個進(jìn)程會向管道中放入信息。管道的另一端連接一個進(jìn)程的輸入,這個進(jìn)程取出被放入管道的信息。一個緩沖區(qū)不需要很大,它被設(shè)計(jì)成為環(huán)形的數(shù)據(jù)結(jié)構(gòu),以便管道可以被循環(huán)利用。
當(dāng)管道中沒有信息的話,從管道中讀取的進(jìn)程會等待,直到另一端的進(jìn)程放入信息。當(dāng)管道被放滿信息的時(shí)候,嘗試放入信息的進(jìn)程會等待,直到另一端的進(jìn)程取出信息。當(dāng)兩個進(jìn)程都終結(jié)的時(shí)候,管道也自動消失。從原理上,管道利用fork機(jī)制建立(參考Linux進(jìn)程基礎(chǔ)和Linux從程序到進(jìn)程),從而讓兩個進(jìn)程可以連接到同一個PIPE上。最開始的時(shí)候,上面的兩個箭頭都連接在同一個進(jìn)程Process 1上(連接在Process 1上的兩個箭頭)。當(dāng)fork復(fù)制進(jìn)程的時(shí)候,會將這兩個連接也復(fù)制到新的進(jìn)程(Process 2)。隨后,每個進(jìn)程關(guān)閉自己不需要的一個連接 (兩個黑色的箭頭被關(guān)閉; Process 1關(guān)閉從PIPE來的輸入連接,Process 2關(guān)閉輸出到PIPE的連接),這樣,剩下的紅色連接就構(gòu)成了如上圖的PIPE。由于基于fork機(jī)制,所以管道只能用于父進(jìn)程和子進(jìn)程之間,或者擁有相同祖先的兩個子進(jìn)程之間 (有親緣關(guān)系的進(jìn)程之間)。為了解決這一問題,Linux提供了FIFO方式連接進(jìn)程。FIFO又叫做命名管道(named PIPE)。
FIFO (First in, First out)為一種特殊的文件類型,它在文件系統(tǒng)中有對應(yīng)的路徑。當(dāng)一個進(jìn)程以讀(r)的方式打開該文件,而另一個進(jìn)程以寫(w)的方式打開該文件,那么內(nèi)核就會在這兩個進(jìn)程之間建立管道,所以FIFO實(shí)際上也由內(nèi)核管理,不與硬盤打交道。之所以叫FIFO,是因?yàn)楣艿辣举|(zhì)上是一個先進(jìn)先出的隊(duì)列數(shù)據(jù)結(jié)構(gòu),最早放入的數(shù)據(jù)被最先讀出來(好像是傳送帶,一頭放貨,一頭取貨),從而保證信息交流的順序。FIFO只是借用了文件系統(tǒng)(file system, 參考Linux文件管理背景知識)來為管道命名。寫模式的進(jìn)程向FIFO文件中寫入,而讀模式的進(jìn)程從FIFO文件中讀出。當(dāng)刪除FIFO文件時(shí),管道連接也隨之消失。FIFO的好處在于我們可以通過文件的路徑來識別管道,從而讓沒有親緣關(guān)系的進(jìn)程之間建立連接。傳統(tǒng)IPC這幾種傳統(tǒng)IPC實(shí)際上有很悠久的歷史,所以其實(shí)現(xiàn)方式也并不完善 (比如說我們需要某個進(jìn)程負(fù)責(zé)刪除建立的IPC)。一個共同的特征是它們并不使用文件操作的API。對于任何一種IPC來說,你都可以建立多個連接,并使用鍵值(key)作為識別的方式。我們可以在一個進(jìn)程中中通過鍵值來使用的想要那一個連接 (比如多個消息隊(duì)列,而我們選擇使用其中的一個)。鍵值可以通過某種IPC方式在進(jìn)程間傳遞(比如說我們上面說的PIPE,FIFO或者寫入文件),也可以在編程的時(shí)候內(nèi)置于程序中。在幾個進(jìn)程共享鍵值的情況下,這些傳統(tǒng)IPC非常類似于多線程共享資源的方式(參看Linux多線程與同步):#:semaphore與mutex類似,用于處理同步問題。我們說mutex像是一個只能容納一個人的洗手間,那么semaphore就像是一個能容納N個人的洗手間。其實(shí)從意義上來說,semaphore就是一個計(jì)數(shù)鎖,它允許被N個進(jìn)程獲得。當(dāng)有更多的進(jìn)程嘗試獲得semaphore的時(shí)候,就必須等待有前面的進(jìn)程釋放鎖。當(dāng)N等于1的時(shí)候,semaphore與mutex實(shí)現(xiàn)的功能就完全相同,一個semaphore會一直存在在內(nèi)核中,直到某個進(jìn)程刪除它。
#:共享內(nèi)存與多線程共享global data和heap類似。一個進(jìn)程可以將自己內(nèi)存空間中的一部分拿出來,允許其它進(jìn)程讀寫。當(dāng)使用共享內(nèi)存的時(shí)候,我們要注意同步的問題。我們可以使用semaphore同步,也可以在共享內(nèi)存中建立mutex或其它的線程同步變量來同步。由于共享內(nèi)存允許多個進(jìn)程直接對同一個內(nèi)存區(qū)域直接操作,所以它是效率最高的IPC方式。
消息隊(duì)列(message queue)與PIPE相類似。它也是建立一個隊(duì)列,先放入隊(duì)列的消息被最先取出。不同的是,消息隊(duì)列允許多個進(jìn)程放入消息,也允許多個進(jìn)程取出消息。每個消息可以帶有一個整數(shù)識別符(message_type)。你可以通過識別符對消息分類 (極端的情況是將每個消息設(shè)置一個不同的識別符)。某個進(jìn)程從隊(duì)列中取出消息的時(shí)候,可以按照先進(jìn)先出的順序取出,也可以只取出符合某個識別符的消息(有多個這樣的消息時(shí),同樣按照先進(jìn)先出的順序取出)。消息隊(duì)列與PIPE的另一個不同在于它并不使用文件API。最后,一個隊(duì)列不會自動消失,它會一直存在于內(nèi)核中,直到某個進(jìn)程刪除該隊(duì)列。
多進(jìn)程協(xié)作可以幫助我們充分利用多核和網(wǎng)絡(luò)時(shí)代帶來的優(yōu)勢。多進(jìn)程可以有效解決計(jì)算瓶頸的問題。互聯(lián)網(wǎng)通信實(shí)際上也是一個進(jìn)程間通信的問題,只不過這多個進(jìn)程分布于不同的電腦上。網(wǎng)絡(luò)連接是通過socket實(shí)現(xiàn)的。由于socket內(nèi)容龐大,所以我們不在這里深入。一個小小的注解是,socket也可以用于計(jì)算機(jī)內(nèi)部進(jìn)程間的通信。
總結(jié)
以上是生活随笔為你收集整理的使用系统调用pipe建立一条管道线_【Linux系统】Linux进程间通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue商城源码_一个标星 5.2k+ 的
- 下一篇: 小程序学习(一):点击爱心变色 -- 最