管道
1 使用訊號進行通訊
程序之間使用「訊號」進行通訊的優缺點
優點:簡單
缺點:傳遞的資訊有限,
只能傳遞乙個簡單的「訊號值」
解決方案:
使用「管道」進行程序間通訊。
注: 程序間通訊,簡稱「ipc」
2 什麼是管道
ipc 有多種方式, 管道是ipc的最基本的方式.
管道是「半雙工」的,即是單向的。
管道是fifo(先進先出)的。
單程序中的管道:
int fd[2]
使用檔案描述符fd[1], 向管道寫資料
使用檔案描述符fd[0], 從管道讀資料
fd[0]
使用者程序
fd[1]
使用者程序
fd[1]
fd[0] 讀 寫
管道
核心
注:單程序中的管道無實際用處
管道用於多程序間通訊。
3 管道的建立
使用pipe系統呼叫
用法:見 man 2 pipe
返回值:
成功:返回 0
失敗:返回 -1
注意:獲取兩個「檔案描述符」
分別對應管道的讀端和寫端。
fd[0]: 是管道的讀端
fd[1]: 是管道的寫端
如果對fd[0]進行寫操作,對fd[1]進行讀操作,可能導致不可預期的錯誤。
4 管道的使用
例項1:單程序使用管道進行通訊
main1. c
注意:建立管道後,獲得該管道的兩個檔案描述符,
不需要普通檔案操作中的open操作
如圖:例項2:多程序使用管道進行通訊
main2.c
注意:建立管道之後,再建立子程序,此時一共有4個檔案描述符。
4個埠,父子程序分別有乙個讀埠和乙個寫埠
向任意乙個寫埠寫資料,即可從任意乙個讀埠獲取資料。
如圖:例項3:子程序使用exec啟動新程式時管道的使用
main3.c
有程式p1, p2
使用管道進行通訊
p1由使用者輸入乙個字串,然後把該字串發給p2
p2接收到以後,把該字串列印出來
p1:
建立管道
建立子程序
在子程序中用exec替換成p2,
(在使用exec 時,把管道的讀端作為exec的引數)
在父程序中,獲取使用者的輸入,然後把所輸入的字串傳送給p2
(即,父程序把字串寫入管道)
p2:
從引數中獲取管道的讀端(引數即為p2的main函式的引數)
讀管道
把讀到的字串列印出來
難點:子程序使用exec啟動新程式執行後,
新程序能夠使用原來子程序的管道(因為exec能共享原來的檔案描述符)
但問題是新程序並不知道原來的檔案描述符是多少!
解決方案:
把子程序中的管道檔案描述符,用exec的引數傳遞給新程序。
例項4:關閉管道的讀端/寫端
管道關閉後的讀操作:
問題:
對管道進行read時,如果管道中已經沒有資料了,此時讀操作將被「阻塞」。
如果此時管道的寫端已經被close了,則寫操作將可能被一直阻塞!
而此時的阻塞已經沒有任何意義了。(因為管道的寫端已經被關閉,即不會再寫入資料了)
解決方案:
如果不準備再向管道寫入資料,則把該管道的所有寫端都關閉,
則,此時再對該管道read時,就會返回0,而不再阻塞該讀操作。(管道的特性)
注意,這是管道的特性。
如果有多個寫埠,而只關閉了乙個寫端,那麼無資料時讀操作仍將被阻塞。
實際實現方式:
父子程序各有乙個管道的讀端和寫端;
把父程序的讀端(或寫端)關閉;
把子程序的寫端(或讀端)關閉;
使這個「4埠」管道變成單向的「2埠」管道,如圖:
**:main4.c
(改寫main2.c)
把父程序的寫操作注釋掉,此時子程序的讀操作將被一直阻塞
把父程序的寫操作注釋掉,並close父程序的寫端
此時子程序的讀操作將將被阻塞。
把父程序的寫操作注釋掉,並把父子程序的寫端都close
此時子程序讀操作將直接返回0,而不再阻塞。
最終實現方案:
關閉父程序的讀端,關閉子程序的寫端。
當父程序不再傳送資料時,就關閉本程序的寫端。
練習:建立乙個子程序
父程序通過管道向子程序傳送資料(字串)
該字串由使用者輸入。
當使用者輸入」exit」時, 就不再向子程序傳送資料,並關閉該端的管道。
子程序從管道讀取資料,並輸出。
直到父程序關閉了管道的寫端。
練習:main5.c
建立乙個子程序
父程序:
迴圈等待使用者輸入,
使用者每輸入乙個單詞後,就把該單詞用管道傳送給子程序,
直到使用者輸入exit。
子程序:
每收到乙個單詞後,就列印輸出
直到使用者在父程序中結束輸入。
例項5 把管道作為標準輸入和標準輸出
把管道作為標準輸入和標準輸出的優點:
子程序使用exec啟動新程式時,就不需要再把管道的檔案描述符傳遞給新程式了。
可以直接使用使用標準輸入(或標準輸出)的程式。
比如 od –c (統計字元個數,結果為八進位制)
實現原理:
使用dup複製檔案描述符
用exec啟動新程式後,原程序中已開啟的檔案描述符仍保持開啟,
即可以共享原程序中的檔案描述符。
**:main6.c (修改main3.c)
注意:dup的用法
dup複製檔案描述符,
返回的新檔案描述符和被複製的檔案描述符,指向同乙個檔案或管道
5 使用popen/pclose
popen的作用:
用來在兩個程式之間傳遞資料:
在程式a中使用popen呼叫程式b時,有兩種用法:
程式a讀取程式b的輸出(使用fread讀取)
程式a傳送資料給程式b,以作為程式b的標準輸入。(使用fwrite寫入)
用法:man popen
返回值:成功,返回file*
失敗, 返回空
例項1: 讀取外部程式的輸出
main7.c
例項2:把輸出寫到外部程式
main8.c
popen的原理:
先使用fork建立乙個子程序,
然後在子程序中使用exec執行指定外部程式,並返回乙個檔案指標file*給父程序。
當使用」r」時,該file指向外部程式的標準輸出
當使用」w」時,該file指向外部程式的標準輸入。
popen的優缺點:
優點:可以使用shell擴充套件(比如命令中可以使用萬用字元)
使用方便。
缺點:每呼叫一次popen, 將要啟動兩個程序(shell和被指定的程式),
資源消耗大。
如果所有管道寫端對應的檔案描述符被關閉,則read返回0
如果所有管道讀端對應的檔案描述符被關閉,則write操作會產生訊號sigpipe
命名管道 匿名管道
有名字 則可以通過 名字 開啟相同的管道進行通訊,沒有名字 在核心中沒有明確標識 只能通過 子程序複製父程序的方式實現通訊,複製了檔案描述符 匿名管道只能用於具有親緣關係的程序間通訊。只要在建立程序之前建立管道,後邊的程序都可以實現通訊。命名管道可用於同一主機任意程序間通訊 作業系統在核心提供的一塊...
命名管道和匿名管道
我們知道程序間是可以通訊的。可以達到資料傳輸 資源共享 事件通知 程序控制等目的。程序間通訊主要包括管道 系統ipc,套接字等。管道分為三種 1 普通管道 int pipe int fds 2 返回值0表示成功,1表示失敗 fd 0 讀 fd 1 寫 子程序往管道中寫資料,寫資料時要關閉讀端 父程序...
語言 管道 建立匿名管道
本質 特點 實現方式 侷限性 匿名管道 僅適用於有血緣關係的程序通訊.本功能實現的是 ps axu grep bash 通過呼叫 ps 和 grep命令 然後分別將他們的輸出 和 輸入的檔案描述符改變.從終端改入到管道中.intmain int argc,char ar pid t pid fork...