新聞中心
Linux操作系統(tǒng)是一個免費、免費開放源代碼的操作系統(tǒng)。它是由極客和程序員們開發(fā)的,已被許多人廣泛使用。其中一個重要的優(yōu)勢是它有許多特性,其中之一是管道。通過管道機制,Linux讓數據流動變得更加容易。

管道是Linux中的一種特殊文件類型。它允許將一個程序的輸出傳遞給另一個程序的輸入。管道的工作原理非常簡單。當一個程序把數據發(fā)送到管道中時,該數據自動傳遞給管道的另一端,另一個程序可讀取該數據。這里我們將介紹Linux管道的工作原理,以及如何在Linux系統(tǒng)中使用管道。
Linux管道原理
在講述Linux管道原理之前,我們先來介紹一些Linux系統(tǒng)中的概念。在Linux系統(tǒng)中,一切都是文件。例如,當您輸入命令并按下Enter鍵時,命令本身可以被視為文件。常常在Linux命令行中看到的紅色的一些詞(例如ls,cat等)也可以被視為文件。文件之間的數據傳輸也是通過文件描述符進行的。在Linux系統(tǒng)中,每個打開的文件都有一個相應的文件描述符。
在Linux系統(tǒng)中,管道被視為文件之一,因此,管道也有一個文件描述符。正因為如此,Linux管道可以被視為兩個程序之間的一條連接。其中一個程序稱為管道的寫端,其他一個程序稱為管道的讀端。
當一個程序把數據寫入管道中時,管道的寫端就變?yōu)榭勺x寫狀態(tài),管道的讀端就會變?yōu)榭勺x狀態(tài),另一個程序就可以讀到管道中的數據。
如何在Linux系統(tǒng)中使用管道
現在讓我們來看看如何在Linux系統(tǒng)中使用管道。您需要有兩個程序,一個為管道的寫端,另一個為管道的讀端。您可以使用以下命令將兩個程序連成一個管道:
program_1 | program_2
在這里,您需要將一個程序的輸出連接到另一個程序的輸入。使用豎杠符號“|”將兩個程序連通。
讓我們來看一個例子。假設您有一個程序A,它生成文本,但是您想要將這個文本寫入文件中。在這種情況下,您可以使用以下命令將程序A的輸出連接到程序B的輸入:
./programA | ./programB > output.txt
這將創(chuàng)建一個管道,將程序A的輸出連接到程序B的輸入。ProgramB將寫入它接收到的數據到output.txt。
管道與大多數Linux命令一起使用非常方便。例如,您可以使用以下命令將列出/etc目錄中的文件和文件夾,然后將該列表按字母順序排序:
ls /etc/ | sort
該命令將列出/etc目錄的內容,連接到sort程序的輸入,將列表按字母順序排序,并將輸出發(fā)送到Linux終端。
Linux管道是Linux系統(tǒng)中的一個非常強大的特性。通過使用Linux管道,多個程序之間的數據流轉可以變得更加方便快捷。管道的工作原理很簡單,通過將一個程序的輸出連接到另一個程序的輸入來建立一條管道。當程序把數據寫入管道中時,另一個程序就可以從管道中讀取這些數據。希望以上內容能夠幫助對Linux管道的工作原理有更好的理解,并能夠更好地應用于Linux系統(tǒng)中。
相關問題拓展閱讀:
- 12 Binder原理-基礎知識點
- Linux的管道命令如何使用?
12 Binder原理-基礎知識點
Binder原理是掌握系統(tǒng)底層原理的基石,也是進階高級工程師的必備知識點,這篇文章不會過多介紹Binder原理,而是講解學習Binder前需要的掌握的知識點。
IPC全名為inter-Process Communication,含義為進程間通信,是指兩個進程之間進行數據交換的過程。在Android和Linux中都有各自的IPC機制,這里分別來介紹下。
Linux中提供了很多進程間通信機制,主要有管道(pipe)、信號(sinal)、信號量(semophore)、消息隊列(Message)、共享內存(Share Memory)、套接字(Socket)等。
管道
管道是Linux由Unix那里繼承過來的進程間的通信機制,它是Unix早期的一個重要通信機制。管道的主要思想是,在內存中創(chuàng)建一個共享文件,從而使通信雙方利用這個共享文件來傳遞信息。這個共享文件比較特殊,它不屬于文件系統(tǒng)并且只存在于內存中。另外還有一點,管道采用的是半雙工通信方式的,數據只能在一個方向上流動。
簡單的模型如下所示。
信號
信號是軟件層次上對中斷機制的一種模擬,是一種異步通信方式,進程不必通過任何操作來等待信號的到達。信號可以在用戶空間進程和內核之間直接交互,內核可以利用信號來通知用戶空間的進程發(fā)生了哪些系統(tǒng)事件。信號不適用于信息交換,比較適用于進程中斷控制。
信號量
信號量是一個計數器,用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。主要作為進程間以及同一進程內不同線程之間的同步手段。
消息隊列
消息隊列是消息的鏈表,具有特定的格式,存放在內存中并由消息隊列標識符標識,并且允許一個或多個進程向它寫入與讀取消息。信息會復制兩次,因此對于頻繁或者信息量大的通信不宜使用消息隊列。
共享內存
多個進程可以直接讀寫的一塊內存空間,是針對其他通信機制運行效率較低而設計的。
為了在多個進程間交換信息,內核專門留出了一塊內存區(qū),可以由需要訪問的進程將其映射到自己的私有地址空間。進程就可以直接讀寫這一塊內存而不需要進行數據的拷貝,從而大大的提高效率。
套接字
套接字是更為基礎的進程間通信機制,與其他方式不同的是,套接字可用于不同機器之間的進程間通信。
Android系統(tǒng)是基于Linux內核的,在Linux內核基礎上,又拓展出了一些IPC機制。Android系統(tǒng)除了支持套接字,還支持序列化、Messenger、AIDL、Bundle、文件共享、ContentProvider、Binder等。Binder會在后面介紹,先來了解前面的IPC機制。
序列化
序列化指的是Serializable/Parcelable,Serializable是Java提供的一個序列化接口,是一個空接口,為對象提供標準的序列化和反序列化操作。Parcelable接口是Android中的序列化方式,更適合在Android平臺上使用,用起來比較麻煩,效率很高。
Messenger
Messenger在Android應用開發(fā)中的使用頻率不高,可以在不同進程中傳遞Message對象,在Message中加入我們想要傳的數據就可以在進程間的進行數據傳遞了。Messenger是一種輕量級的IPC方案并對AIDL進行了封裝。
AIDL
AIDL全名為Android interface definition Language,即Android接口定義語言。Messenger是以串行的方式來處理客戶端發(fā)來的信息,如果有大量的消息發(fā)到服務端,服務端仍然一個一個的處理再響應客戶端顯然是不合適的。另外還有一點,Messenger用來進程間進行數據傳遞但是卻不能滿足跨進程的方法調用,這個時候就需要使用AIDL了。
Bundle
Bundle實現了Parcelable接口,所以它可以方便的在不同的進程間傳輸。Acitivity、Service、Receiver都是在Intent中通過Bundle來進行數據傳遞。
文件共享
兩個進程通過讀寫同一個文件來進行數據共享,共享的文件可以是文本、XML、JOSN。文件共享適用于對數據同步要求不高的進程間通信。
ContentProvider
ContentProvider為存儲和獲取數據了提供統(tǒng)一的接口,它可以在不同的應用程序之間共享數據,本身就是適合進程間通信的。ContentProvider底層實現也是Binder,但是使用起來比AIDL要容易許多。系統(tǒng)中很多操作都采用了ContentProvider,例如通訊錄,音視頻等,這些操作本身就是跨進程進行通信。
在講到Linux的進程通信原理之前,我們需要先了解Liunx中的幾個概念。
內核空間和用戶空間
當我們接觸到Liunx時,免不了聽到兩個詞,User space(用戶空間)和 Kernel space(內核空間),那么它們的含義是什么呢?
為了保護用戶進程不能直接操作內核,保證內核的安全,操作系統(tǒng)從邏輯上將虛擬空間劃分為用戶空間和內核空間。Linux 操作系統(tǒng)將更高的1GB字節(jié)供內核使用,稱為內核空間,較低的3GB 字節(jié)供各進程使用,稱為用戶空間。
內核空間是Linux內核的運行空間,用戶空間是用戶程序的運行空間。為了安全,它們是隔離的,即使用戶的程序崩潰了,內核也不會受到影響。內核空間的數據是可以進程間共享的,而用戶空間則不可以。比如在上圖進程A的用戶空間是不能和進程B的用戶空間共享的。
進程隔離
進程隔離指的是,一個進程不能直接操作或者訪問另一個進程。也就是進程A不可以直接訪問進程B的數據。
系統(tǒng)調用
用戶空間需要訪問內核空間,就需要借助系統(tǒng)調用來實現。系統(tǒng)調用是用戶空間訪問內核空間的唯一方式,保證了所有的資源訪問都是在內核的控制下進行的,避免了用戶程序對系統(tǒng)資源的越權訪問,提升了系統(tǒng)安全性和穩(wěn)定性。
進程A和進程B的用戶空間可以通過如下系統(tǒng)函數和內核空間進行交互。
內存映射
由于應用程序不能直接操作設備硬件地址,所以操作系統(tǒng)提供了一種機制:內存映射,把設備地址映射到進程虛擬內存區(qū)。
舉個例子,如果用戶空間需要讀取磁盤的文件,如果不采用內存映射,那么就需要在內核空間建立一個頁緩存,頁緩存去拷貝磁盤上的文件,然后用戶空間拷貝頁緩存的文件,這就需要兩次拷貝。
采用內存映射,如下圖所示。
由于新建了虛擬內存區(qū)域,那么磁盤文件和虛擬內存區(qū)域就可以直接映射,少了一次拷貝。
內存映射全名為Memory Map,在Linux中通過系統(tǒng)調用函數mmap來實現內存映射。將用戶空間的一塊內存區(qū)域映射到內核空間。映射關系建立后,用戶對這塊內存區(qū)域的修改可以直接反應到內核空間,反之亦然。內存映射能減少數據拷貝次數,實現用戶空間和內核空間的高效互動。
了解Liunx中的幾個概念后,就可以學習Linux的IPC通信原理了,如下圖所示。
內核程序在內核空間分配內存并開辟一塊內核緩存區(qū),發(fā)送進程通過copy_from_user函數將數據拷貝到到內核空間的緩沖區(qū)中。同樣的,接收進程在接收數據時在自己的用戶空間開辟一塊內存緩存區(qū),然后內核程序調用 copy_to_user() 函數將數據從內核緩存區(qū)拷貝到接收進程。這樣數據發(fā)送進程和數據接收進程完成了一次數據傳輸,也就是一次進程間通信。
Linux的IPC通信原理有兩個問題:
Binder是基于開源的OpenBinder實現的,OpenBinder最早并不是由Google公司開發(fā)的,而是Be Inc公司開發(fā)的,接著由Palm, Inc.公司負責開發(fā)。后來OpenBinder的作者Dianne Hackborn加入了Google公司,并負責Android平臺的開發(fā)工作,順便把這項技術也帶進了Android。
Binder是基于內存映射來實現的,在前面我們知道內存映射通常是用在有物理介質的文件系統(tǒng)上的,Binder沒有物理介質,它使用內存映射是為了跨進程傳遞數據。
Binder通信的步驟如下所示。
1.Binder驅動在內核空間創(chuàng)建一個數據接收緩存區(qū)。
2.在內核空間開辟一塊內核緩存區(qū),建立內核緩存區(qū)和數據接收緩存區(qū)之間的映射關系,以及數據接收緩存區(qū)和接收進程用戶空間地址的映射關系。
3.發(fā)送方進程通過copy_from_user()函數將數據拷貝 到內核中的內核緩存區(qū),由于內核緩存區(qū)和接收進程的用戶空間存在內存映射,因此也就相當于把數據發(fā)送到了接收進程的用戶空間,這樣便完成了一次進程間的通信。
整個過程只使用了1次拷貝,不會因為不知道數據的大小而浪費空間或者時間,效率更高。
Android是基于Linux內核的 ,Linux提供了很多IPC機制,而Android卻自己設計了Binder來進行通信,主要是因為以下幾點。
性能方面
性能方面主要影響的因素是拷貝次數,管道、消息隊列、Socket的拷貝次書都是兩次,性能不是很好,共享內存不需要拷貝,性能更好,Binder的拷貝次書為1次,性能僅次于內存拷貝。
穩(wěn)定性方面
Binder是基于C/S架構的,這個架構通常采用兩層結構,在技術上已經很成熟了,穩(wěn)定性是沒有問題的。共享內存沒有分層,難以控制,并發(fā)同步訪問臨界資源時,可能還會產生死鎖。從穩(wěn)定性的角度講,Binder是優(yōu)于共享內存的。
安全方面
Android是一個開源的系統(tǒng),并且擁有開放性的平臺,市場上應用來源很廣,因此安全性對于Android 平臺而言極其重要。
傳統(tǒng)的IPC接收方無法獲得對方可靠的進程用戶ID/進程ID(UID/PID),無法鑒別對方身份。Android 為每個安裝好的APP分配了自己的UID,通過進程的UID來鑒別進程身份。另外,Android系統(tǒng)中的Server端會判斷UID/PID是否滿足訪問權限,而對外只暴露Client端,加強了系統(tǒng)的安全性。
語言方面
Linux是基于C語言,C語言是面向過程的,Android應用層和Java Framework是基于Java語言,Java語言是面向對象的。Binder本身符合面向對象的思想,因此作為Android的通信機制更合適不過。
從這四方面來看,Linux提供的大部分IPC機制根本無法和Binder相比較,而共享內存只在性能方面優(yōu)于Binder,其他方面都劣于Binder,這些就是為什么Android要使用Binder來進行進程間通信,當然系統(tǒng)中并不是所有的進程通信都是采用了Binder,而是根據場景選擇最合適的,比如Zygote進程與AMS通信使用的是Socket,Kill Process采用的是信號。
Binder機制在Android中的地位舉足輕重,我們需要掌握的很多原理都和Binder有關:
上面只是列了一小部分,簡單來說說,比如系統(tǒng)在啟動時,SystemServer進程啟動后會創(chuàng)建Binder線程池,目的是通過Binder,使得在SystemServer進程中的服務可以和其他進程進行通信了。再比如我們常說的AMS、PMS都是基于Binder來實現的,拿PMS來說,PMS運行在SystemServer進程,如果它想要和DefaultContainerService通信(是用于檢查和復制可移動文件的系統(tǒng)服務),就需要通過Binder,因為DefaultContainerService運行在com.android.defcontainer進程。
還有一個比較常見的C/S架構間通信的問題,Client端的MediaPlayer和Server端的MeidaPlayerService不是運行在一個進程中的,同樣需要Binder來實現通信。
可以說Binder機制是掌握系統(tǒng)底層原理的基石。
上圖并沒有給出Binder機制的具體的細節(jié),而是先給出了一個概念,根據系統(tǒng)的Android系統(tǒng)的分層。
Linux的管道命令如何使用?
管道命令就是用來連接多條指令的,前一條指令的輸出流向會作為后一條指含掘鬧令的操作對象。
管道命令的操作符是:|,它只能處理由前面一條指令傳出的正確輸出信息,對錯誤信息是沒有直接處理能力的。然后,傳遞給下一條指令,作為操作對象。
基本格式:
指令1 | 指令2 | …
【指令1】正確輸出,作散廳為【指令2】的輸入,然后【指令2】的輸出作為【指令3】的輸入,如果【指令3】有輸出,那么輸出談罩就會直接顯示在屏幕上面了。通過管道之后【指令1】和【指令2】的正確輸出是不顯示在屏幕上面的。
【提醒注意】
管道命令只能處理前一條指令的正確輸出,不能處理錯誤輸出;
管道命令的后一條指令,必須能夠接收標準輸入流命令才能執(zhí)行。
使用示例
1、分頁顯示/etc目錄中內容的詳細信息
$ ls -l /etc | more
2、將一個字符串輸入到一個文件中
$ echo “hello world” | cat > hello.txt
1.linux管道命令具有過濾特性,一條命令通過標準輸入端口接收一個文件中的數據,命令執(zhí)行后產生的結果數據又通過標準輸出端口送給后一條命令,作為第二條罩猜命令的輸入數據。第二條數據也是通過標準輸入端口接收輸入數據。shell提供管塵畢道命令|把這派悶芹些命令前后銜接在一起,形成一個管道線。2.ps -ef|grep mysqld 這個豎線|就是管道命令的體現。
關于linux管道實現原理的介紹到此就結束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關注本站。
香港服務器選創(chuàng)新互聯,2H2G首月10元開通。
創(chuàng)新互聯(www.cdcxhl.com)互聯網服務提供商,擁有超過10年的服務器租用、服務器托管、云服務器、虛擬主機、網站系統(tǒng)開發(fā)經驗。專業(yè)提供云主機、虛擬主機、域名注冊、VPS主機、云服務器、香港云服務器、免備案服務器等。
當前標題:Linux管道的工作原理簡介(linux管道實現原理)
路徑分享:http://m.fisionsoft.com.cn/article/djddsop.html


咨詢
建站咨詢
