轉載於:http://blog.csdn.net/followingturing/article/details/6071937
前面在一段小程序中看到了mkfifo這樣的一個函數,在baidu了一下之后對於進程間通信產生了一點興趣,所以就小小的研究了一下。
在一個多進程操作系統所提供的運行環境下,可以通過兩種不同的途徑或者說采用兩種不同的策略,來建立起復雜的大型應用系統。一種途徑就是通過一個孤立的,大型的,復雜的進程提供所需的全部服務,另外一種途徑就是通過由若干相互聯系的,小型的。相對簡單的進程構成的組合來提供所需的功能。早期的操作系統往往傾向與前者,而Unix以及其衍生的各種操作系統往往傾向於后者。相比之下,后者有着各種好處:1.模塊化,2.各個進程都得到保護,在相當程度上排除了相互干擾的可能性,3.靈活性更強。
當然這種好處也是要付出代價的,也有缺點,但是相比之下,這種途徑的優點遠遠超出了其缺點。
Unix(從而Linux)向應用軟件提供了一些進程間通信的手段,早期的Unix提供了:管道(pipe),信號(signal),跟蹤(trace)。
這里我們只談管道:父進程與子進程,或者兩個兄弟進程之間,可以通過系統調用建立起一個單向的通信管道。但是,這種管道只能由父進程來建立,所以對於子進程來說是靜態的,與生俱來的。管道兩端的進程各自將該管道視作一個文件。一個進程往通道中寫的內容由另一個進程從通道讀出,通過通道傳遞的內容遵循“先入先出”(FIFO)的規則。每個通道都是單向的,需要雙向通信時要建立起兩個通道。
下面說一說進程間管道的建立,在這之前我們要說到fork()函數,在Linux系統中一個新的進程是由一個已經存在的進程“復制”出來的,而不是“創造”出來的(而所謂的“創建”實際上就是復制)。
管道機制的主體是系統調用pipe(),但是由pipe()所建立的管道的兩端都在同一個進程中,這樣的管道起不到進程間通信的作用。所以必須在fork()的配合下,才能在父子進程間或者兩個子進程之間建立起進程間的通信管道。
下面就介紹一下怎樣將管道用於進程間通信:
(1)進程A創建了一個管道,創建完成時代表管道兩端的兩個已打開文件都在進程A中。
(2)進程A通過frok()創建出進程B,在fork()的過程中進程A的打開文件表按原樣復制到進程B中。
(3)進程A關閉管道的讀端,而進程B關閉管道的寫段。於是,管道的寫段在進程A中而讀端在進程B中,成為了父子進程之間的通信管道。
(4)進程A又通過frok()創建進程C,而后關閉其管道寫段而與管道脫離關系,使得管道的寫段在進程C中而讀端在進程B中,成為兩個兄弟進程之間的管道。
人們在認識到管道機制也存在一些缺點和不足。由於管道是一種“無名”,“無形”的文件,它可以通過fork()的過程創建於“近親” 的進程之間,而不能成為可以在任意兩個進程之間建立通信的機制,更不可能成為一種一般的,通用的進程間通信模型,同時,管道機制的這種缺點本身強烈的暗示着人們,只要用“有名”,“有形”的文件來實現管道,就能克服這種缺點。所以有了管道之后,“命名管道”的出現時必然的。
為了實現“命名管道”,在“普通文件”,“塊設備文件”,“字符設備文件”之外,又設立了一種文件類型,稱為FIFO文件。對這種文件的訪問嚴格遵循“先進先出”的原則。這樣就可以像在磁盤上建立一個文件一樣建立一個命名管道,具體可以使用命令mknod來建立。例如:
% mknod mypipe p
這里的參數“p”表示所建立的節點的類型。
我們從——help中可以看出:
b create a block (buffered) special file
c, u create a character (unbuffered) special file
p create a FIFO
至於管道的具體使用,大家可以連接下面的一個網址
http://blog.163.com/zqs1111/blog/static/37203887200946344191
