圖解Linux進程間通信實現原理(1)


為Linux應用程序的開發人員,對Linux的進程間通信方式肯定是了如指掌,平時的開發中應該會大量的使用到。當你迅速的在鍵盤上按下【CTRL+C】終止掉一個正在運行中的命令時,你有沒有仔細的思考過背后的原理呢?或者是他們是通過什么通信方式呢?這個通信方式是怎樣實現的呢?本文就帶着大家去Linux進程間通信一探究竟,找出他們的原理。

概念

我們都知道,應用程序在運行起來之后(進程),是相互獨立的,都有自己的進程地址空間。但是往往在一些業務上需要進程間的通信,來完成系統的某個完整的功能。我們來看下進程間通信能干那些事情?首先當然最重要的是:

  1. 數據傳輸。一個進程需要發送數據到另一個進程,這種需求肯定是存在的。
  2. 共享數據。如果有多個進程想要訪問數據,一個進程修改了內容,另一個進程能夠立即看到內容變化。
  3. 資源保護:上面的的操作中存在競爭情況,內核需要提供鎖和同步機制。
  4. 通知:一個進程需要向另一個進程發送消息,通知發生了某個事件。
  5. 控制:有些進程需要控制另一個進程的運行。典型的例子就是gdb,可參考之前文章【gdb到底是怎么實現的?】

 

通信方式

進程間的通信方式一般可以分為八種,如下:

 

圖解Linux進程間通信實現原理(1),經典干貨

八種通信方式

 

他們在不同的標准都有不同的實現,如下圖所示:

 

圖解Linux進程間通信實現原理(1),經典干貨

通信方式框圖

 

 

我們先從管道開始講起來吧。

管道

這里說的管理特指的是無名管道,它是一種半雙工的通信方式。也就是說數據只能單向流動,一般是在具有親緣關系的進程間使用,比如父子進程。當一個進程創建了一個管道,並調用fork創建自己的一個子進程后,父進程關閉讀管道端,子進程關閉寫管道端,這樣提供了兩個進程之間數據流動的一種方式。

管道是怎么通信的呢?

首先管道是內核的一個緩沖區,而且是在內存中。管道一頭連接着一個進程的輸出,另一頭連接着另一個進程的輸入。一個緩沖區不需要很大,它被設計成為環形的數據結構,以便管道可以被循環利用。當管道中沒有信息的話,從管道中讀取的進程會等待,直到另一端的進程放入信息。當管道被放滿信息的時候,嘗試放入信息的進程會等待,直到另一端的進程取出信息。當兩個進程都終結的時候,管道也自動消失。看下圖:

 

圖解Linux進程間通信實現原理(1),經典干貨

 

 

那管道怎樣建立的呢?

從原理上,管道利用fork機制建立,從而讓兩個進程可以連接到同一個PIPE上。最開始的時候,上面的兩個箭頭都連接在同一個進程1上(連接在進程1上的兩個箭頭),如下圖。當fork復制進程的時候,會將這兩個連接也復制到新的進程(進程2)。隨后,每個進程關閉自己不需要的一個連接 (兩個黑色的箭頭被關閉; 進程1關閉從PIPE來的輸入連接,進程2關閉輸出到PIPE的連接),這樣,剩下的紅色連接就構成了如上圖的PIPE。

 

圖解Linux進程間通信實現原理(1),經典干貨

 

 

 

管道在內核中具體怎么實現的呢?

在Linux內核中,並沒有針對管道新增數據結構。而是巧妙的借用了文件系統的file結構和虛擬文件系統的索引節點inode。通過將兩個 file 結構指向同一個臨時的 VFS 索引節點,而這個 VFS 索引節點又指向一個物理頁面而實現的。

 

圖解Linux進程間通信實現原理(1),經典干貨

 

 

具體實現

管道的實現其實也不難,源代碼在內核工程中的fs/pipe.c,我們着重的講兩個比較重要的接口吧,也就是常用的pipe_read()和pipe_write(),前者是管道讀函數,后者是管道寫函數。

管道寫函數將字節數據復制到虛擬文件系統索引節點指向的物理內存頁,而讀函數則是相反:讀出數據。當然這里存在着競爭的管理,需要一定的同步機制,使用鎖,等待隊列和信號。

當我們寫的時候,調用write(),內核根據傳入的文件描述符fd,找到該文件的file結構。然后執行結構中f_op中的寫函數。寫函數在向內存寫入數據之前,必須首先檢查虛擬文件系統索引節點信息,檢查是否有足夠的內存空間可以寫和內存沒有被讀程序鎖定這兩個條件,只有滿足了,才真正的進行內存拷貝。

接下來寫函數就會鎖定內存,然后復制數據到內存,否則就在虛擬文件系統inode的等待隊列中。

管道的讀取過程和寫入過程類似。但是,進程可以在沒有數據或內存被鎖定時立即返回錯誤信息,而不是阻塞該進程,這依賴於文件或管道的打開模式。反之,進程可以休眠在索引節點的等待隊列中等待寫入進程寫入數據。當所有的進程完成了管道操作之后,管道的索引節點被丟棄,而共享數據頁也被釋放。

總結

由於篇幅的限制,八大進程間通信只講了管道,文章開頭的疑問也只能等到后續文章了,也算是留個懸念吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM