Linux 實現 IPC 其中的一種方式——管道

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