自己的理解,
首先要區分概念:管道和管道通訊
所謂「管道」,是指用於連線乙個讀程序和乙個寫程序以實現它們之間通訊的乙個共享檔案,又名pipe檔案
(是一種特殊的檔案,這就意味著你可以向操作檔案一樣操作無名管道,無名管道在核心中對應的是一段特殊的記憶體空間,這段記憶體空間由作業系統進行管理,對使用者是不可見的,在使用者空間的應用程式中只能通過系統呼叫來訪問它。在這段記憶體空間中以迴圈佇列的方式來臨時儲存乙個程序發往另外乙個程序的資訊,並且在通訊完成後就會自動釋放相應的空間。)
而管道通訊是訊息傳遞的一種特殊方式。
即管道是檔案,是服務於管道通訊的特殊檔案,而管道通訊是一種通訊方式,這種通訊方式比較特殊,是半雙工的通訊方式,即資料只能單向流動,資料傳遞的方式是字元流形式,它一般是應用在具有共同祖先的程序間使用。
管道通訊是什麼? 用於程序之間通訊的一種通訊方式。
管道通訊有哪些特點? 半雙工的通訊方式,資料只能單向流動,資料傳遞的方式是字元流形式。
管道通訊的應用場合? 具有共同祖先的程序間使用。
管道:—就像現實中的水管,水就像資料。(連線程序,相當於在程序間連線乙個通路,用來傳遞資訊)
—管道是一種半雙工的通訊方式
—資料只能單向流動,而且只能在具有共同祖先的程序間使用。
所謂半雙工的模式
(假設通訊雙方是甲方和乙方,雙工通訊方式的意思是甲可以向乙傳送資料,乙也可以向甲傳送資料,即資料流通是雙向的。而半雙工的通訊方式是指甲乙兩方不能同時向對方傳送資料,也就是甲向乙傳送資料時,乙只能接收不能傳送,而乙向甲傳送資料時,甲只能接收不能向乙傳送資料)
舉個例子:
形象來說類似乙個單刀雙擲開關,有兩個選擇,但是二者是互斥的,當選擇了一方另一方就失效。
而對於此處的管道,可以把它想成是管道的一端,一次只能呼叫一種功能讀入或者寫入,二者也是互斥的。
管道通訊是訊息傳遞的一種特殊方式,管道機制必須提供以下三方面的協調能力:互斥、同步和確定對方的存在。
在乙個多程序作業系統所提供的執行環境下,可以通過兩種不同的途徑或者說採用兩種不同的策略,來建立起複雜的大型應用系統。一種途徑就是通過乙個孤立的,大型的,複雜的程序提供所需的全部服務,另外一種途徑就是通過由若干相互聯絡的,小型的。相對簡單的程序構成的組合來提供所需的功能。早期的作業系統往往傾向與前者,而unix以及其衍生的各種作業系統往往傾向於後者。相比之下,後者有著各種好處:1.模組化,2.各個程序都得到保護,在相當程度上排除了相互干擾的可能性,3.靈活性更強。
當然這種好處也是要付出代價的,也有缺點,但是相比之下,這種途徑的優點遠遠超出了其缺點。
unix(從而linux)向應用軟體提供了一些程序間通訊的手段,早期的unix提供了:管道(pipe),信(signal),跟蹤(trace)。
程序之間的通訊,從物理上分,可以分為同主機的程序之間的通訊和不同主機間的程序之間的通訊。從通訊內容方式上分,可以分為資料互動、同步通訊、非同步通訊。
linux
系統程序之間的通訊方式大致如下圖所示
集合上述兩種從物理和內容方式的劃分,可以這樣理解上圖:
(1)同主機程序間資料互動機制:無名管道(pipe)、有名管道(fifo)、訊息佇列(message queue)和共享記憶體(shared memory)。
(2)同主機程序間同步通訊機制:訊號量(semaphore)。
(3)同主機程序間非同步通訊機制:訊號(signal)。
(4)不同主機間程序資料互動機制:套接字(socket)、遠端呼叫rpc(remote procedure call)。
管道通訊
管道又可以分為無名管道和命名管道,兩者的用途是不一樣的。
無名管道pipe:主要用於具有親緣關係的程序之間的通訊,無名管道的通訊是單向的,只能由一段到另外一段;無名管道是臨時性的,完成通訊後將自動消失。一般採用先建立無名管道,再建立子程序,使子程序繼承父程序的管道檔案描述符,從而實現父子程序間的通訊;在非親緣關係管道之間,如果想利用無名管道進行通訊,則需要借助另外的檔案描述符傳遞機制。
有名管道fifo:有名管道是乙個實際存在的特殊檔案,利用有名管道可以實現同主機任意程序之間的資料互動。
無名管道是一種特殊的檔案,這就意味著你可以向操作檔案一樣操作無名管道,無名管道在核心中對應的是一段特殊的記憶體空間,這段記憶體空間由作業系統進行管理,對使用者是不可見的,在使用者空間的應用程式中只能通過系統呼叫來訪問它。在這段記憶體空間中以迴圈佇列的方式來臨時儲存乙個程序發往另外乙個程序的資訊,並且在通訊完成後就會自動釋放相應的空間。
即無名管道主要用於具有親緣關係的父子程序之間的通訊,是臨時性的,需要先建立管道,再建立子程序;管道都是單向的,若要實現雙向通訊,則需要兩個管道。命名管道是實際存在的檔案,使用前需要先開啟,管道預設的read和write操作都是阻塞式的。
這裡我們只談管道:父程序與子程序,或者兩個兄弟程序之間,可以通過系統呼叫建立起乙個單向的通訊管道。但是,這種管道只能由父程序來建立,所以對於子程序來說是靜態的,與生俱來的。管道兩端的程序各自將該管道視作乙個檔案。乙個程序往通道中寫的內容由另乙個程序從通道讀出,通過通道傳遞的內容遵循「先入先出」(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來建立。
函式介紹:
¢int read(intfd, void *buf, int count);
—功能:從引數fd指定的讀端讀取管道資料到大小為count的快取buf中,返回實際讀取到的位元組數。
—引數¢fd:管道讀端
¢buf:快取區,儲存讀到的資料
¢count:讀取位元組數
•intwrite(intfd, void *buf, intcount);
•功能:向引數fd指定的寫端從快取buf中取出count個位元組到管道中,返回值為實際寫入的位元組數。
•引數•fd:管道寫端
•buf:快取區,將要寫入管道的資料
•count:寫入的位元組數
程序通訊 管道通訊
程序間通訊 目的 資料傳輸 乙個程序需要將它的資料傳送給另乙個程序 資源共享 多個程序之間共享同樣的資源 通知事件 乙個程序需要向另乙個或一組程序傳送訊息,通知它們發生了某種事件 程序控制 有些程序希望完全控制另乙個程序的執行 如debug程序 此時控制程序希望能夠攔截另乙個程序的所有操作,並能夠及...
linux 程序通訊 管道通訊
程序通訊 1 pipe 函式的作用 建立無名管道 函式的原型 int pipe int fds 2 函式的引數 新建的兩個描述符fds陣列返回 fds 0 表示管道的讀取端 fds 1 表示管道的寫入端 返回值 成功 0 出錯 1 標頭檔案 include 2 mkfifo 函式的作用 建立有名管道...
程序間通訊 管道
include int pipe int fd 2 返回值 若成功,返回0,若出錯,返回 1經由引數fd返回兩個檔案描述符 fd 0 為讀而開啟,fd 1 為寫而開啟。fd 1 的輸出是fd 0 的輸入。else if pid 0 子程序 else else if pid 0 父程序 printf ...