Linux 實(shí)現(xiàn) IPC 其中的一種方式——管道
創(chuàng)新互聯(lián)建站專(zhuān)注于武平網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供武平營(yíng)銷(xiāo)型網(wǎng)站建設(shè),武平網(wǎng)站制作、武平網(wǎng)頁(yè)設(shè)計(jì)、武平網(wǎng)站官網(wǎng)定制、微信平臺(tái)小程序開(kāi)發(fā)服務(wù),打造武平網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供武平網(wǎng)站排名全網(wǎng)營(yíng)銷(xiāo)落地服務(wù)。
管道又分:
1、無(wú)名管道:無(wú)名管道只能用于有親緣關(guān)系的進(jìn)程。
2、有名管道:有名管道用于任意兩進(jìn)程間通信。
你就可以把管道理解成位于進(jìn)程內(nèi)核空間的“文件”。
給文件加引號(hào),是因?yàn)樗臀募_實(shí)很像,因?yàn)樗灿忻枋龇5撬_實(shí)又不是普通的本地文件,而是一種抽象的存在。
當(dāng)進(jìn)程使用 pipe 函數(shù),就可以打開(kāi)位于內(nèi)核中的這個(gè)特殊“文件”。同時(shí) pipe 函數(shù)會(huì)返回兩個(gè)描述符,一個(gè)用于讀,一個(gè)用于寫(xiě)。如果你使用 fstat函數(shù)來(lái)測(cè)試該描述符,可以發(fā)現(xiàn)此文件類(lèi)型為 FIFO。
而無(wú)名管道的無(wú)名,指的就是這個(gè)虛幻的“文件”,它沒(méi)有名字。本質(zhì)上,pipe 函數(shù)會(huì)在進(jìn)程內(nèi)核空間申請(qǐng)一塊內(nèi)存(比如一個(gè)內(nèi)存頁(yè),一般是 4KB),然后把這塊內(nèi)存當(dāng)成一個(gè)先進(jìn)先出(FIFO)的循環(huán)隊(duì)列來(lái)存取數(shù)據(jù),這一切都由操作系統(tǒng)幫助我們實(shí)現(xiàn)了。
pipe 函數(shù)打開(kāi)的文件描述符是通過(guò)參數(shù)(數(shù)組)傳遞出來(lái)的,而返回值表示打開(kāi)成功(0)或失?。?1)。
它的參數(shù)是一個(gè)大小為 2 的數(shù)組。此數(shù)組的第 0 個(gè)元素用來(lái)接收以讀的方式打開(kāi)的描述符,而第 1 個(gè)元素用來(lái)接收以寫(xiě)的方式打開(kāi)的描述符。也就是說(shuō),pipefd[0] 是用于讀的,而 pipefd[1] 是用于寫(xiě)的。
打開(kāi)了文件描述符后,就可以使用 read(pipefd[0]) 和 write(pipefd[1]) 來(lái)讀寫(xiě)數(shù)據(jù)了。
注意事項(xiàng)
1、這兩個(gè)分別用于讀寫(xiě)的描述符必須同時(shí)打開(kāi)才行,否則會(huì)出問(wèn)題。
2、如果關(guān)閉讀 (close(pipefd[0])) 端保留寫(xiě)端,繼續(xù)向?qū)懚?(pipefd[1]) 端寫(xiě)數(shù)據(jù)(write 函數(shù))的進(jìn)程會(huì)收到 SIGPIPE 信號(hào)。
3、如果關(guān)閉寫(xiě) (close(pipefd[1])) 端保留讀端,繼續(xù)向讀端 (pipefd[0]) 端讀數(shù)據(jù)(read 函數(shù)),read 函數(shù)會(huì)返回 0。
當(dāng)在進(jìn)程用 pipe 函數(shù)打開(kāi)兩個(gè)描述符后,我們可以 fork 出一個(gè)子進(jìn)程。這樣,子進(jìn)程也會(huì)繼承這兩個(gè)描述符,而且這兩個(gè)文件描述符的引用計(jì)數(shù)會(huì)變成 2。
如果你需要父進(jìn)程向子進(jìn)程發(fā)送數(shù)據(jù),那么得把父進(jìn)程的 pipefd[0] (讀端)關(guān)閉,而在子進(jìn)程中把 pipefd[1] 寫(xiě)端關(guān)閉,反之亦然。為什么要這樣做?實(shí)際上是避免出錯(cuò)。傳統(tǒng)上 pipe 管道只能用于半雙工通信(即一端只能發(fā),不能收;而另一端只能收不能發(fā)),為了安全起見(jiàn),各個(gè)進(jìn)程需要把不用的那一端關(guān)閉(本質(zhì)上是引用計(jì)數(shù)減 1)。
步驟一:fork 子進(jìn)程
步驟二:關(guān)閉父進(jìn)程讀端,關(guān)閉子進(jìn)程寫(xiě)端
父進(jìn)程 fork 出一個(gè)子進(jìn)程,通過(guò)無(wú)名管道向子進(jìn)程發(fā)送字符,子進(jìn)程收到數(shù)據(jù)后將字符串中的小寫(xiě)字符轉(zhuǎn)換成大寫(xiě)并輸出。
有名管道打破了無(wú)名管道的限制,進(jìn)化出了一個(gè)實(shí)實(shí)在在的 FIFO 類(lèi)型的文件。這意味著即使沒(méi)有親緣關(guān)系的進(jìn)程也可以互相通信了。所以,只要不同的進(jìn)程打開(kāi) FIFO 文件,往此文件讀寫(xiě)數(shù)據(jù),就可以達(dá)到通信的目的。
1、文件屬性前面標(biāo)注的文件類(lèi)型是 p
2、代表管道文件大小是 0
3、fifo 文件需要有讀寫(xiě)兩端,否則在打開(kāi) fifo 文件時(shí)會(huì)阻塞
通過(guò)命令 mkfifo 創(chuàng)建
通過(guò)函數(shù) mkfifo創(chuàng)建
函數(shù)返回 0 表示成功,-1 失敗。
例如:
cat 命令打印 test文件內(nèi)容
接下來(lái)你的 cat 命令被阻塞住。
開(kāi)啟另一個(gè)終端,執(zhí)行:
然后你會(huì)看到被阻塞的 cat 又繼續(xù)執(zhí)行完畢,在屏幕打印 “hello world”。如果你反過(guò)來(lái)執(zhí)行上面兩個(gè)命令,會(huì)發(fā)現(xiàn)先執(zhí)行的那個(gè)總是被阻塞。
有兩個(gè)程序,分別是發(fā)送端 send 和接收端面 recv。程序 send 從標(biāo)準(zhǔn)輸入接收字符,并發(fā)送到程序 recv,同時(shí) recv 將接收到的字符打印到屏幕。
發(fā)送端
接收端
編譯
運(yùn)行
因?yàn)?recv 端還沒(méi)打開(kāi)test文件,這時(shí)候 send 是阻塞狀態(tài)的。
再開(kāi)啟另一個(gè)終端:
這時(shí)候 send 端和 recv 端都在終端顯示has opend fifo
此時(shí)在 send 端輸入數(shù)據(jù),recv 打印。
管道命令就是用來(lái)連接多條指令的,前一條指令的輸出流向會(huì)作為后一條指令的操作對(duì)象。
管道命令的操作符是:|,它只能處理由前面一條指令傳出的正確輸出信息,對(duì)錯(cuò)誤信息是沒(méi)有直接處理能力的。然后,傳遞給下一條指令,作為操作對(duì)象。
基本格式:
指令1 | 指令2 | …
【指令1】正確輸出,作為【指令2】的輸入,然后【指令2】的輸出作為【指令3】的輸入,如果【指令3】有輸出,那么輸出就會(huì)直接顯示在屏幕上面了。通過(guò)管道之后【指令1】和【指令2】的正確輸出是不顯示在屏幕上面的。
【提醒注意】
管道命令只能處理前一條指令的正確輸出,不能處理錯(cuò)誤輸出;
管道命令的后一條指令,必須能夠接收標(biāo)準(zhǔn)輸入流命令才能執(zhí)行。
使用示例
1、分頁(yè)顯示/etc目錄中內(nèi)容的詳細(xì)信息
$ ls -l /etc | more
2、將一個(gè)字符串輸入到一個(gè)文件中
$ echo “hello world” | cat hello.txt
pipe函數(shù)的原型是:
int pipe(int file_descriptor[2]);
它需要的頭文件是:#include unistd.h
pipe函數(shù)的參數(shù)是一個(gè)有兩個(gè)文件描述符(整型)元素的數(shù)組,pipe函數(shù)在數(shù)組中填入兩個(gè)新的文件描述符后返回0,失敗則返回1。
怎么用呢,成功的調(diào)用pipe函數(shù)后,向file_descriptor[1]寫(xiě)入的所有數(shù)據(jù),可以從file_descriptor[0]讀出來(lái)。使用情景:在一個(gè)調(diào)用fork的程序中,利用pipe從子進(jìn)程和父進(jìn)程之間傳遞數(shù)據(jù)。
注意:pipe函數(shù)的數(shù)組參數(shù)是文件描述符,不是文件流,所以不能用C標(biāo)準(zhǔn)庫(kù)函數(shù),而是應(yīng)該用read和write系統(tǒng)調(diào)用來(lái)讀寫(xiě)數(shù)據(jù)。
示例:
int file_pipes[2];
if(pipe(file_pipes)==0) {
// 向file_pipes[1]寫(xiě)數(shù)據(jù)
// 從file_pipes[0]讀數(shù)據(jù)
}
本文名稱(chēng):linux命令pipe linux命令拼接
標(biāo)題來(lái)源:http://sd-ha.com/article22/doipocc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、定制開(kāi)發(fā)、自適應(yīng)網(wǎng)站、軟件開(kāi)發(fā)、用戶(hù)體驗(yàn)、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)