Linux的管道機制和重定向
1.管道機制
在Linux中,管道是一種使用非常頻繁的通訊機制。從本質上說,管道也是一種檔案,但它又和一般的檔案有所不同,管道可以克服使用檔案進行通訊的兩個問題,具體表現為:
· 限制管道的大小。實際上,管道是一個固定大小的緩衝區。在Linux中,該緩衝區的大小為1頁,即4K位元組,使得它的大小不象文件那樣不加檢驗地增長。使用單個固定緩衝區也會帶來問題,比如在寫管道時可能變滿,當這種情況發生時,隨後對管道的write()調用將預設地被阻塞,等待某些資料被讀取,以便騰出足夠的空間供write()呼叫寫。
· 讀取程式也可能工作得比寫程式快。當所有當前程式資料已被讀取時,管道變空。當這種情況發生時,一個隨後的read()呼叫將預設地被阻塞,等待某些資料被寫入,這解決了read()呼叫返回檔案結束的問題。
注意:從管道讀資料是一次性操作,資料一旦被讀,它就從管道中被拋棄,釋放空間以便寫更多的資料。
1. 1.管道的結構
在 Linux 中,管道的實現並沒有使用專門的資料結構,而是藉助了檔案系統的file結構和VFS的索引節點inode。通過將兩個 file 結構指向同一個臨時的VFS 索引節點,而這個 VFS 索引節點又指向一個物理頁面而實現的。如圖 7.1所示。
圖7.1 管道結構示意圖
圖7.1中有兩個 file 資料結構,但它們定義檔案操作例程地址是不同的,其中一個是向管道中寫入資料的例程地址,而另一個是從管道中讀出資料的例程地址。這樣,使用者程式的系統呼叫仍然是通常的檔案操作,而核心卻利用這種抽象機制實現了管道這一特殊操作。
1.2.管道的讀寫
管道實現的原始碼在fs/pipe.c中,在pipe.c中有很多函式,其中有兩個函式比較重要,即管道讀函式pipe_read()和管道寫函式pipe_wrtie()。管道寫函式通過將位元組複製到 VFS 索引節點指向的實體記憶體而寫入資料,而管道讀函式則通過複製實體記憶體中的位元組而讀出資料。當然,核心必須利用一定的機制同步對管道的訪問,為此,核心使用了鎖、等待佇列和訊號。
當寫程式向管道中寫入時,它利用標準的庫函式write(),系統根據庫函式傳遞的檔案描述符,可找到該檔案的 file 結構。file 結構中指定了用來進行寫操作的函式(即寫入函式)地址,於是,核心呼叫該函式完成寫操作。寫入函式在向記憶體中寫入資料之前,必須首先檢查 VFS 索引節點中的資訊,同時滿足如下條件時,才能進行實際的記憶體複製工作:
記憶體中有足夠的空間可容納所有要寫入的資料;
記憶體沒有被讀程式鎖定。
如果同時滿足上述條件,寫入函式首先鎖定記憶體,然後從寫程式的地址空間中複製資料到記憶體。否則,寫入程式就休眠在 VFS 索引節點的等待佇列中,接下來,核心將呼叫排程程式,而排程程式會選擇其他程式執行。寫入程式實際處於可中斷的等待狀態,當內存中有足夠的空間可以容納寫入資料,或記憶體被解鎖時,讀取程式會喚醒寫入程式,這時,寫入程式將接收到訊號。當資料寫入內存之後,記憶體被解鎖,而所有休眠在索引節點的讀取程式會被喚醒。
管道的讀取過程和寫入過程類似。但是,程式可以在沒有資料或記憶體被鎖定時立即返回錯誤資訊,而不是阻塞該程式,這依賴
檔案或管道的開啟模式。反之,程式可以休眠在索引節點的等待佇列中等待寫入程式寫入資料。當所有的程式完成了管道操作之
後,管道的索引節點被丟棄,而共享資料頁也被釋放。
因為管道的實現涉及很多檔案的操作,因此,當讀者學完有關檔案系統的內容後來讀pipe.c中的程式碼,你會覺得並不難理解。
1.3.管道的使用
例如檢視python的程式,ps是檢視程式命令,-e是檢視所有程式,f是全格式顯示,|是管道符號,grep是模糊過濾將ps -ef的輸出流通過管道作為輸入流輸入grep python命令中,有grep輸入結果
ps –ef |grep python
2.重定向
>filename,重定向標準輸出到檔案,覆蓋檔案。>>filename,重定向標準輸出到檔案,追加模式。
2>filename,重定向標準錯誤到檔案。
&>filename,重定向標準輸入和標準錯誤到檔案。相當於同時使用>和2>。
<filename,重定向標準輸入自檔案
舉個例子,在用find的時候,有的目錄不允許訪問,find就輸出很多行的錯誤,真正的搜尋結果就看不到了。這時我會把標準錯誤重定向到空檔案去:
find/ -name "filename" 2> /dev/null
再比如在用gdb進行自動測試的時候,把命令寫到一個檔案裡,然後送入gdb。
gdbprogram < test_script.gdb
相關文章
- Linux中重定向和管道介紹Linux
- 在Linux中,管道(pipe)和重定向(redirection)的是什麼?Linux
- Linux大檔案重定向和管道的效率對比總結Linux
- linux3-管道符、重定向、環境變數Linux變數
- 輸出重定向 管道
- 介紹 Linux 中的管道和命名管道Linux
- 015 Linux 標準輸入輸出、重定向、管道和後臺啟動程式命令Linux
- ASP.NET Core 中的管道機制ASP.NET
- Redis學習之管道機制Redis
- Zsh 開發指南(第十三篇 管道和重定向)
- linux中的輸入與輸出管理(重定向輸入,輸出,管道符)Linux
- 管道符、重定向與環境變數變數
- linux的I/O重定向和管道的檔案描述符運用,及shell如何實現多執行緒?Linux執行緒
- 【linux】管道!!!Linux
- Linux 管道Linux
- [Linux]管道Linux
- CentOS 管道符、重定向與環境變數CentOS變數
- Linux重定向Linux
- Linux管道符Linux
- Linux 之管道Linux
- Linux安全機制Linux
- Linux OOM 機制LinuxOOM
- 框架篇:Linux零拷貝機制和FileChannel框架Linux
- Linux歸檔及壓縮、重定向與管道操作、find精確查詢、vim高階使用Linux
- Linux就該這麼學:重定向,管道符,萬用字元,轉義符,環境變數Linux字元變數
- Linux中的保護機制Linux
- linux管道詳解Linux
- linux——管道詳解Linux
- Linux 的程式間通訊:管道Linux
- Linux 資料重定向Linux
- linux 訊號機制Linux
- Linux中重定向應注意的事情Linux
- Linux中的許可權機制Linux
- Linux-task_struct和檔案系統及管道的關係LinuxStruct
- Linux 下的程式間通訊:使用管道和訊息佇列Linux佇列
- Linux系統中的管道命令、grep命令、sed命令和awk命令Linux
- Linux核心記憶體保護機制:aslr和canaryLinux記憶體
- Linux命令學習(重定向)Linux