進程通訊就至關於一種工做方式、溝通形式,好比你給我一個SVN標籤號而且告知我意圖,我去庫中檢索指定標籤修改的指定內容,就完成了一個任務的協做。
進程同步中,也有信息的交換,好比互斥量訪問,再好比生產者和消費者,共享緩衝池,可是這些一般被稱之爲低級的進程通訊。
以信號量爲例,若是你說我在塔頂點亮燈表示危險,不然表示安全,這沒問題,若是你想用燈亮燈滅來像QQ同樣,大段大段的傳遞訊息可能麼?
多搞幾盞燈?而後用編碼?即便那樣你依然是很費力的。
因此說盡管好比信號量機制做爲同步工具是卓有成效的,但做爲通訊工具,則不夠方便
首先是效率低,另外共享數據結構的設置、數據的傳送、進程的互斥與同步等,都必須由程序員本身去實現
因此,對於進程間的通訊,咱們迫切的渴望有「封裝好的方法」
進程通訊主要指的就是操做系統提供的進程通訊工具(「封裝好的方法」)用來進程間的信息交換。
進程通訊類型
主要有四種通訊方式
共享存儲器系統
共享存儲系統關鍵在於共享
主要兩種:
管道通訊
這種方式獨創於UNIX 系統,因爲它能有效地傳送大量數據,於是又被引入到許多其它的操做系統中
管道指用於鏈接一個讀進程和一個寫進程以實現它們之間通訊的一個共享文件,這個文件又被叫作pipe文件
管道能夠理解爲一種比較特殊的「共享存儲器系統」的通訊方式
消息傳遞系統
在該機制中,進程沒必要藉助任何共享存儲區或數據結構,而是以格式化的消息(message)爲單位,將通訊的數據封裝在消息中
並利用操做系統提供的一組通訊命令(原語),在進程間進行消息傳遞,完成進程間的數據交換
計算機網絡中的報文就是一種message
消息傳遞系統中的消息,其實也是「共享數據結構」的一種形式,是一種特殊的形式
由於被共享的數據結構而不是隨便自定義的,而是你們共同設計好的,承認的,一致的一種格式。
基於這種一致性的格式,而後操做系統對他提供了支持
因此,他就是共享數據結構的一個特例,這個特例使用更加方便簡單。
簡單說,計算機報文是一種message,那麼操做系統對整個TCP/IP協議棧的實現,這就是通訊命令,封裝了底層的傳輸細節,對開發者來講是透明的
客戶服務器系統
客戶機一服務器系統的通訊機制,在網絡環境的各類應用領域已成爲當前主流的通訊實現機制
BS架構的系統本質也是包裝演化的CS,瀏覽器難道不是客戶端軟件麼
主要有三種:
遠程過程調用 RPC(Remote Procedure Call),RPC採用客戶機/服務器模式,請求程序就是一個客戶機,而服務提供程序就是一個服務器
RPC容許你 透明的 調用遠程服務器上提供的服務
對於面向對象的編程中,遠程過程調用一般也被稱爲遠程方法調用
好比java1.1中實現的Remote Method Invocation,RMI,能夠認爲是RPC的Java版本,RMI大大加強了Java開發分佈式應用的能力。
歸納地說的話:
遠程過程調用RPC是一種協議概念,它是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。
RPC不依賴於具體的網絡傳輸協議,tcp、udp等均可以。
協議必然須要被實現才能使用,他只是一種協議與標準,RMI就至關因而sun對RPC的一個Java實現
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,是更加底層的通訊工具,因此能夠認爲RPC是socket的上層建築
一個或許不是很合適的比喻:若是RPC是議論文格式,那麼RMI多是漢語的議論文,socket多是漢字
套接字原理步驟
雙方進程運行在不一樣主機的網絡環境下,被分配了一對套接字,一個屬於接收進程(或服務器端),一個屬於發送進程(或客戶端)。
發送進程(或客戶端)發出鏈接請求時,隨機申請一個套接字,主機爲之分配一個端口,與該套接字綁定,再也不分配給其它進程。
接收進程(或服務器端)擁有全局公認的套接字和指定的端口(如ftp服務器監聽端口爲21,Web或http服務器監聽端口爲80),並經過監聽端口等待客戶請求。所以,任何進程均可以向它發出鏈接請求和信息請求,以方便進程之間通訊鏈接的創建。
接收進程(或服務器端)一旦收到請求,就接受來自發送進程(或客戶端)的鏈接,完成鏈接,即在主機間傳輸的數據能夠準確地發送到通訊進程,實現進程間的通訊;
當通訊結束時,系統經過關閉接收進程(或服務器端)的套接字撤銷鏈接。
遠程過程原理步驟
負責RPC的調用的進程有兩個,一個是本地客戶進程,另外一個是遠程服務進程,這兩個進程也被稱之爲網絡守護進程,主要負責網絡之間的消息傳遞
一般處於阻塞之中,等待消息。
而遠程過程調用的透明化核心就是所謂的存根,也叫作樁stub
因此說兩個進程和兩個存根是RPC的根本
樁的原理
樁相似代理者、轉換器一類的角色
舉一個例子:在一些與底層硬件芯片等交互的軟件層,軟件層依賴底層芯片的處理,如何更方便的進行代碼測試?
也就是至關於A類中有方法functionA,B類中有方法functionB(假定functionB 是硬件處理部分,測試並不方便,須要依賴設備)
functionA(){
functionB();
}
咱們就能夠編寫一個新的類C,提供樁方法:functionStubC,全部調用functionB的地方所有使用functionStubC,也就是
functionA(){
functionStubC();
}
而functionStubC的返回值,永遠是functionB成功的返回值。
這就是一個打樁的概念。
RPC也是經過這個樁的概念來實現透明的遠程過程調用
對本地調用來講,他看到的只是客戶端存根(stub)
就如同咱們上面的functionStubC,固然比functionStubC要更加複雜,全部的處理都在他背後被執行
因此對本地調用來講是透明的
RPC過程步驟
- 本地過程調用者以通常方式調用遠程過程在本地關聯的客戶存根,傳遞相應的參數,而後將控制權轉移給客戶存根;
- 客戶存根執行,完成包括過程名和調用參數等信息的消息創建,將控制權轉移給本地客戶進程;
- 本地客戶進程完成與服務器的消息傳遞,將消息發送到遠程服務器進程;
- 遠程服務器進程接收消息後轉入執行,並根據其中的遠程過程名找到對應的服務器存根,將消息轉給該存根;
- 該服務器存根接到消息後,由阻塞狀態轉入執行狀態,拆開消息從中取出過程調用的參數,而後以通常方式調用服務器上關聯的過程;
- 在服務器端的遠程過程運行完畢後,將結果返回給與之關聯的服務器存根;
- 該服務器存根得到控制權運行,將結果打包爲消息,並將控制權轉移給遠程服務器進程:
- 遠程服務器進程將消息發送回客戶端;
- 本地客戶進程接收到消息後,根據其中的過程名將消息存入關聯的客戶存根,再將控制權轉移給客戶存根;
- 客戶存根從消息中取出結果,返回給本地調用者進程,並完成控制權的轉移。
總結
進程通訊的一些核心思想與基本形式就是上面的這些簡介
這些是最純粹基本的理論知識,而對於咱們實際的開發中,面對的老是各類各樣的對於現存的理論的實現版本
核心仍舊是依賴操做系統以及語言自己的實現以及一些框架等
可是理解這些概念是必要的,能讓你後續的學習路線愈來愈明朗,技術是層不出窮的,你僅僅學習招式,永遠也沒法窮盡,還致使本身沒有底蘊。