每一個進程各自有不一樣的用戶地址空間,任何一個進程的變量在另外一個進程中都是看不到的,因此進程之間要交換數據必須經過內核,在內核中開闢出一塊緩衝區。一個進程把本身的數據從用戶空間拷貝到內核緩衝區,另外一個進程再從內核緩衝區把數據讀走。內核提供的這種機制稱爲進程間通訊(IPC,Inter Process Communication)網絡
Linux進程間基本的通訊方式主要有:管道(pipe)(包括匿名管道和命名管道)、信號(signal)、消息隊列(queue)、共享內存、信號量和套接字。異步
下面逐漸介紹這幾種方式:函數
1.管道:管道的實質是一個內核緩衝區,管道的做用正如其名,須要通訊的兩個進程在管道的兩端,進程利用管道傳遞信息。管道對於管道兩端的進程而言,就是一個文件,可是這個文件比較特殊,它不屬於文件系統而且只存在於內存中。設計
管道依據是否有名字分爲匿名管道和命名管道(有名管道),這兩種管道有必定的區別。隊列
匿名管道有幾個重要的限制:進程
命名管道容許沒有親緣關係的進程進行通訊。命名管道不一樣於匿名管道之處在於它提供了一個路徑名與之關聯,這樣一個進程即便與建立有名管道的進程不存在親緣關係,只要能夠訪問該路徑,就能經過有名管道互相通訊。事件
2.信號:信號是軟件層次上對中斷機制的一種模擬,是一種異步通訊方式,進程沒必要經過任何操做來等待信號的到達。信號能夠在用戶空間進程和內核之間直接交互,內核能夠利用信號來通知用戶空間的進程發生了哪些系統事件。ip
信號來源:內存
信號事件的發生有兩個來源:硬件來源,好比咱們按下了鍵盤或者其它硬件故障;軟件來源,最經常使用發送信號的系統函數是kill, raise, alarm和setitimer以及sigqueue函數,軟件來源還包括一些非法運算等操做。資源
進程對信號的響應:
進程能夠經過三種方式來響應信號:(1)忽略信號,即對信號不作任何處理,可是有兩個信號是不能忽略的:SIGKLL和SIGSTOP;(2)捕捉信號,定義信號處理函數,當信號發生時,執行相應的處理函數;(3)執行缺省操做,Linux對每種信號都規定了默認操做。
3.消息隊列:消息隊列是消息的鏈表,具備特定的格式,存放在內存中並由消息隊列標識符標識,而且容許一個或多個進程向它寫入與讀取消息
4.共享內存:使得多個進程能夠能夠直接讀寫同一塊內存空間,是針對其餘通訊機制運行效率較低而設計的。
爲了在多個進程間交換信息,內核專門留出了一塊內存區,能夠由須要訪問的進程將其映射到本身的私有地址空間。進程就能夠直接讀寫這一塊內存而不須要進行數據的拷貝,從而大大提升效率。
須要注意的是:共享內存並未提供同步機制,在一個進程結束對共享內存的寫操做以前,並沒有自動機制能夠阻止另二個進程開始對它進行讀取。因此,咱們一般須要用其餘的機制來同步對共享內存的訪問。
5.信號量:信號量實質上就是一個標識可用資源數量的計數器,它的值老是非負整數。而只有0和1兩種取值的信號量叫作二進制信號量(或二值信號量),可用用來標識某個資源是否可用。
6.套接字:套接字是更爲基礎的進程間通訊機制,與其餘方式不一樣的是,套接字可用於不一樣機器之間的進程間通訊。
有兩種類型的套接字:基於文件的和麪向網絡的。
(1).Unix套接字是基於文件的,而且擁有一個「家族名字」--AF_UNIX,它表明地址家族(address family):UNIX。
(2).第二類型的套接字是基於網絡的,它也有本身的家族名字--AF_INET,表明地址家族(address family):INTERNET
無論採用哪一種地址家族,都有兩種不一樣的套接字鏈接:面向鏈接的和無鏈接的。
(1)面向鏈接的套接字(SOCK_STREAM):進行通訊前必須創建一個鏈接,面向鏈接的通訊提供序列化的、可靠地和不重複的數據交付,而沒有記錄邊界。
這意味着每條信息能夠被拆分紅多個片斷,而且每一個片斷都能確保到達目的地,而後在目的地將信息拼接起來。
實現這種鏈接類型的主要協議是傳輸控制協議(TCP)。
(2)無鏈接的套接字(SOCK_DGRAM):在通訊開始以前並不須要創建鏈接,在數據傳輸過程當中並沒有法保證它的順序性、可靠性或重複性。
然而,數據報確實保存了記錄邊界,這就意味着消息是以總體發送的,而並不是首先分紅多個片斷。
因爲面向鏈接的套接字所提供的保證,所以它們的設置以及對虛擬電路鏈接的維護須要大量的開銷。然而,數據報不須要這些開銷,即它的成本更加「低廉」
實現這種鏈接類型的主要協議是用戶數據報協議(UDP)。