Linux 實現(xiàn) IPC 其中的一種方式——管道
蜀山網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),蜀山網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為蜀山上1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的蜀山做網(wǎng)站的公司定做!
管道又分:
1、無名管道:無名管道只能用于有親緣關(guān)系的進程。
2、有名管道:有名管道用于任意兩進程間通信。
你就可以把管道理解成位于進程內(nèi)核空間的“文件”。
給文件加引號,是因為它和文件確實很像,因為它也有描述符。但是它確實又不是普通的本地文件,而是一種抽象的存在。
當進程使用 pipe 函數(shù),就可以打開位于內(nèi)核中的這個特殊“文件”。同時 pipe 函數(shù)會返回兩個描述符,一個用于讀,一個用于寫。如果你使用 fstat函數(shù)來測試該描述符,可以發(fā)現(xiàn)此文件類型為 FIFO。
而無名管道的無名,指的就是這個虛幻的“文件”,它沒有名字。本質(zhì)上,pipe 函數(shù)會在進程內(nèi)核空間申請一塊內(nèi)存(比如一個內(nèi)存頁,一般是 4KB),然后把這塊內(nèi)存當成一個先進先出(FIFO)的循環(huán)隊列來存取數(shù)據(jù),這一切都由操作系統(tǒng)幫助我們實現(xiàn)了。
pipe 函數(shù)打開的文件描述符是通過參數(shù)(數(shù)組)傳遞出來的,而返回值表示打開成功(0)或失敗(-1)。
它的參數(shù)是一個大小為 2 的數(shù)組。此數(shù)組的第 0 個元素用來接收以讀的方式打開的描述符,而第 1 個元素用來接收以寫的方式打開的描述符。也就是說,pipefd[0] 是用于讀的,而 pipefd[1] 是用于寫的。
打開了文件描述符后,就可以使用 read(pipefd[0]) 和 write(pipefd[1]) 來讀寫數(shù)據(jù)了。
注意事項
1、這兩個分別用于讀寫的描述符必須同時打開才行,否則會出問題。
2、如果關(guān)閉讀 (close(pipefd[0])) 端保留寫端,繼續(xù)向?qū)懚?(pipefd[1]) 端寫數(shù)據(jù)(write 函數(shù))的進程會收到 SIGPIPE 信號。
3、如果關(guān)閉寫 (close(pipefd[1])) 端保留讀端,繼續(xù)向讀端 (pipefd[0]) 端讀數(shù)據(jù)(read 函數(shù)),read 函數(shù)會返回 0。
當在進程用 pipe 函數(shù)打開兩個描述符后,我們可以 fork 出一個子進程。這樣,子進程也會繼承這兩個描述符,而且這兩個文件描述符的引用計數(shù)會變成 2。
如果你需要父進程向子進程發(fā)送數(shù)據(jù),那么得把父進程的 pipefd[0] (讀端)關(guān)閉,而在子進程中把 pipefd[1] 寫端關(guān)閉,反之亦然。為什么要這樣做?實際上是避免出錯。傳統(tǒng)上 pipe 管道只能用于半雙工通信(即一端只能發(fā),不能收;而另一端只能收不能發(fā)),為了安全起見,各個進程需要把不用的那一端關(guān)閉(本質(zhì)上是引用計數(shù)減 1)。
步驟一:fork 子進程
步驟二:關(guān)閉父進程讀端,關(guān)閉子進程寫端
父進程 fork 出一個子進程,通過無名管道向子進程發(fā)送字符,子進程收到數(shù)據(jù)后將字符串中的小寫字符轉(zhuǎn)換成大寫并輸出。
有名管道打破了無名管道的限制,進化出了一個實實在在的 FIFO 類型的文件。這意味著即使沒有親緣關(guān)系的進程也可以互相通信了。所以,只要不同的進程打開 FIFO 文件,往此文件讀寫數(shù)據(jù),就可以達到通信的目的。
1、文件屬性前面標注的文件類型是 p
2、代表管道文件大小是 0
3、fifo 文件需要有讀寫兩端,否則在打開 fifo 文件時會阻塞
通過命令 mkfifo 創(chuàng)建
通過函數(shù) mkfifo創(chuàng)建
函數(shù)返回 0 表示成功,-1 失敗。
例如:
cat 命令打印 test文件內(nèi)容
接下來你的 cat 命令被阻塞住。
開啟另一個終端,執(zhí)行:
然后你會看到被阻塞的 cat 又繼續(xù)執(zhí)行完畢,在屏幕打印 “hello world”。如果你反過來執(zhí)行上面兩個命令,會發(fā)現(xiàn)先執(zhí)行的那個總是被阻塞。
有兩個程序,分別是發(fā)送端 send 和接收端面 recv。程序 send 從標準輸入接收字符,并發(fā)送到程序 recv,同時 recv 將接收到的字符打印到屏幕。
發(fā)送端
接收端
編譯
運行
因為 recv 端還沒打開test文件,這時候 send 是阻塞狀態(tài)的。
再開啟另一個終端:
這時候 send 端和 recv 端都在終端顯示has opend fifo
此時在 send 端輸入數(shù)據(jù),recv 打印。
管道不支持像,ls mv cp 等,
如果要用到這些命令,就要在管道后加參數(shù):xarg
如:which touch | xarg ls -la 就行了。
管道命令就是用來連接多條指令的,前一條指令的輸出流向會作為后一條指令的操作對象。
管道命令的操作符是:|,它只能處理由前面一條指令傳出的正確輸出信息,對錯誤信息是沒有直接處理能力的。然后,傳遞給下一條指令,作為操作對象。
基本格式:
指令1 | 指令2 | …
【指令1】正確輸出,作為【指令2】的輸入,然后【指令2】的輸出作為【指令3】的輸入,如果【指令3】有輸出,那么輸出就會直接顯示在屏幕上面了。通過管道之后【指令1】和【指令2】的正確輸出是不顯示在屏幕上面的。
【提醒注意】
管道命令只能處理前一條指令的正確輸出,不能處理錯誤輸出;
管道命令的后一條指令,必須能夠接收標準輸入流命令才能執(zhí)行。
使用示例
1、分頁顯示/etc目錄中內(nèi)容的詳細信息
$ ls -l /etc | more
2、將一個字符串輸入到一個文件中
$ echo “hello world” | cat hello.txt
管道命令符 " | " 的作用是將前一個命令的標準輸出當作后一個命令的標準輸入,格式為"命令A|命令B"。
例如:
搜索rsyslogd進程: $ ps -ef | grep rsyslogd
用反野形式查看/etc 目錄中有哪些文件: $ ls -l /etc/ | more
bash解釋器支持多種文本通配符,包括:
我們之前在學文本查詢搜索命令時就用到了通配符,例如,在 /etc 目錄下搜索所有的以host開頭的文件:
$ find /etc -name "host*"
另外,bash解釋器還支持很多的特殊字符擴展:
例如:
先定義名稱為PRICE的變量值為5
$ PRICE=5
輸出“價格是5”:
輸出“價格是$5”,但因為美元符號與代表變量取值的$符號沖突,所以需要用到轉(zhuǎn)義字符:
使用單引號,變量將不再被取值:
執(zhí)行 uname -a 后可以查看到本機內(nèi)核的版本與架構(gòu)信息(反引號里面的命令會被執(zhí)行):
簡單來說就是,一個命令的結(jié)果作為另外一個命令(結(jié)果)的輸入,管道是linux提供的一種常見的進程通信工具,也是很多shell命令能夠靈活組合產(chǎn)生強大用途的一個重要工具。
管道是Linux由Unix那里繼承過來的進程間的通信機制,它是Unix早期的一個重要通信機制。其思想是,在內(nèi)存中創(chuàng)建一個共享文件,從而使通信雙方利用這個共享文件來傳遞信息。由于這種方式具有單向傳遞數(shù)據(jù)的特點,所以這個作為傳遞消息的共享文件就叫做“管道”。
在管道的具體實現(xiàn)中,根據(jù)通信所使用的的文件是否具有名稱,有“匿名管道”和“命名管道”。
利用Linux所提供的管道符“|”將兩個命令隔開,管道符左邊命令的輸出就會作為管道符右邊命令的輸入。 連續(xù)使用管道意味著第一個命令的輸出會作為 第二個命令的輸入,第二個命令的輸出又會作為第三個命令的輸入,依此類推。下面來看看管道是如何在構(gòu)造一條Linux命令中得到應(yīng)用的。
注意:
1、管道命令只處理前一個命令正確輸出,不處理錯誤輸出。
2、管道命令右邊命令,必須能夠接收標準輸入流命令才行。
這條命令使用一個管道符“|”建立了一個管道。管道將rpm -qa命令的輸出(包括系統(tǒng)中所有安裝的RPM包)作為grep命令的輸入,從而列出帶有l(wèi)icq字符的RPM包來。
這條命令使用了兩個管道,利用第一個管道將cat命令(顯示passwd文件的內(nèi)容)的輸出送給grep命令,grep命令找出含有“/bin /bash”的所有行;第二個管道將grep的輸出送給wc命令,wc命令統(tǒng)計出輸入中的行數(shù)。這個命令的功能在于找出系統(tǒng)中有多少個用戶使用bash。
區(qū)別是:
1、左邊的命令應(yīng)該有標準輸出 | 右邊的命令應(yīng)該接受標準輸入
左邊的命令應(yīng)該有標準輸出 右邊只能是文件
左邊的命令應(yīng)該需要標準輸入 右邊只能是文件
2、管道觸發(fā)兩個子進程執(zhí)行"|"兩邊的程序;而重定向是在一個進程內(nèi)執(zhí)行
這些都是網(wǎng)上總結(jié)很多的,其實只要多加清楚用法,也一定有自己的一份不同描述。