Linux內核-進程間通訊組件的實現

Linux內核的五大組件

一個完整的Linux內核通常由五大部分組成,他們分別是內存管理,進程管理,進程間通訊,虛擬文件系統和網絡接口。golang

1、內存管理

內存管理主要完成的是如何合理有效地管理整個系統的物理內存,同時快速響應內核各個子系統對內存分配的請求。Linux內存管理支持虛擬內存,而多餘出的這部份內存就是經過磁盤申請獲得的,平時系統只把當前運行的程序塊保留在內存中,其餘程序塊則保留在磁盤中。在內存緊缺時,內存管理負責在磁盤和內存間交換程序塊。算法

2、進程管理

進程管理主要控制系統進程對CPU的訪問。當須要某個進程運行時,由進程調度器根據基於優先級的調度算法啓動新的進程。:Linux支持多任務運行,那麼如何在一個單CPU上支持多任務呢?這個工做就是由進程調度管理來實現的。在系統運行時,每一個進程都會分得必定的時間片,而後進程調度器根據時間片的不一樣,選擇每一個進程依次運行,例如當某個進程的時間片用完後,調度器會選擇一個新的進程繼續運行。因爲切換的時間和頻率都很是的快,由此用戶感受是多個程序在同時運行,而實際上,CPU在同一時間內只有一個進程在運行,這一切都是進程調度管理的結果。網絡

進程間通訊主要用於控制不一樣進程之間在用戶空間的同步、數據共享和交換。因爲不用的用戶進程擁有不一樣的進程空間,所以進程間的通訊要藉助於內核的中轉來實現。通常狀況下,當一個進程等待硬件操做完成時,會被掛起。當硬件操做完成,進程被恢復執行,而協調這個過程的就是進程間的通訊機制。函數

3、進程間通訊

進程間通訊主要用於控制不一樣進程之間在用戶空間的同步、數據共享和交換。因爲不用的用戶進程擁有不一樣的進程空間,所以進程間的通訊要藉助於內核的中轉來實現。通常狀況下,當一個進程等待硬件操做完成時,會被掛起。當硬件操做完成,進程被恢復執行,而協調這個過程的就是進程間的通訊機制。學習

(1)進程間通訊的目的網絡傳輸協議

  • 數據傳輸:一個進程須要將它的數據發送給另外一個進程;
  • 資源共享:多個進程之間共享一樣的資源;
  • 通知事件:一個進程須要向另外一個或者另外一組進程發送消息,通知他們發生了某種事件。
  • 進程控制:有些進程須要徹底控制另外一個進程的執行,此時控制進程但願可以攔截另外一個進程的全部陷入和異常,並可以及時知道它的狀態改變。

(2)進程間通訊方式spa

進程間通訊主要分爲兩大標準:System V 標準和 POSIX 標準。
關於System V標準的進程間通訊主要有如下幾類:
1. 管道
管道適用於進程間的數據傳輸。本質上管道是操做系統在內核中爲進程開闢了一塊緩衝區,多個進程經過訪問同一緩衝區進行通訊,數據在緩衝區中以讀寫的方式被不一樣進程獲取和操做。
管道有三大特性:
1.生命週期隨進程;
2.自帶同步與互斥;
3.提供字節流服務。
管道主要分爲匿名管道和命名管道操作系統

匿名管道code

前面說了管道是操做系統爲進程在內核中分配的一塊緩衝區,匿名管道就是指這塊緩衝區沒有標識符,所以其餘進程沒法直接訪問匿名管道,只有相似父子進程這樣的具備親緣關係的進程才能使用匿名管道進行通訊(緣由是子進程會複製父進程的PCB,其中包括這塊信息)。匿名管道的建立使用以下接口:
int pipe(int fd[2])

這個接口的做用是建立一個匿名管道,並向用戶返回這個管道的操做句柄,其中參數fd[2]中fd[0]用於從管道中讀取數據,fd[1]用於從管道中寫入數據,若是建立成功返回 0, 建立失敗返回 -1.
匿名管道的特性是:
1.若管道中沒有數據,使用讀操做會阻塞;協程

  1. 若管道寫滿了,使用寫操做會阻塞;
  2. 若管道的寫端關閉了,讀完數據以後不會阻塞而是返回 0;

4.若管道的讀端關閉了,繼續寫入數據會觸發異常,程序退出。
這些特性體現了管道自帶同步與互斥。

命名管道

命名管道和匿名管道相反,命名管道是有標識符的一塊緩衝區,而且這個標識符通常是一個可見於文件系統的文件。因此命名管道是一個特殊類型的文件,其餘進程能夠經過這個標識符找到這塊緩衝區,即經過打開同一個管道文件,訪問到同一緩衝區,進而實現進程間通訊。
建立一個命名管道既可使用mkfifo filename命令也可使用接口,函數接口以下:
int mkfifo(const char* pathname, mode_t mode)

參數pathname是命名管道文件的名稱,mode是文件權限 。若是建立成功返回0,失敗返回-1.
命名管道的打開特性:
1.若管道文件以只讀的方式打開,會阻塞,直到這個文件被以寫的方式打開;
2.若管道文件以只寫的方式打開,會阻塞,直到這個文件被以讀的方式打開;
3.若文件以讀寫的方式打開,就不會阻塞。
不論是匿名仍是命名管道,同查那個對管道進行的數據操做的大小不超過PIPE_BUF這個宏的大小,默認是4KB。

2.共享內存
共享內存用於進程間的數據共享,是最快的進程間通訊。共享內存的建立大概是如下步驟:首先,在物理內存中開闢一塊空間,將這塊物理內存映射到程序的虛擬地址空間,進程就能夠經過虛擬地址來訪問這塊內存。多個進程映射到同一物理內存,這樣進行通訊的方式,不須要進入內核,只須要再共享的內存區進行操做便可。其餘方式的通訊都是由於內核中的緩衝區,進程在通訊的時候會涉及內核態和用戶態的兩次數據拷貝。而共享內存不會因此速度更快。

  • 共享內存的操做流程:
    1.建立共享內存即開闢具備標識符的物理內存空間;
    2.將共享內存映射到各個進程的虛擬地址空間;
    3.直接經過虛擬地址進行對共享內存的操做;
    4.解除映射;
    5.釋放共享內存。
int shmget(key_t key, int size, int flag)  //建立一個共享內存

void* shmat(int shmid, void* addr, int flag) //創建映射

int shmdt(void* shmstart) //解除映射

int shmctl(int shmid, int cmd, struct shmid_ds* bf) //操做共享內存
//cmd參數爲IC_RMID的時候是刪除共享內存

當刪除共享內存的時候,共享內存不會當即被刪除(由於可能形成正在訪問的進程奔潰)而是將key修改爲0,表示這塊共享內存不會再接收映射連接,當這塊共享內存的映射連接爲0的時候,則自動釋放。
須要注意的是共享內存自帶沒有同步與互斥。
3. 消息隊列
消息隊列用於進程間的數據傳輸(有標識符)
消息隊列實際上就是內核中的一個優先級隊列,多個進程經過向同一個隊列中 添加 或者 獲取 節點來實現通訊。主要是傳輸一個有類型(優先級)的數據塊。
特性:
1.自帶同步與互斥;
2.生命週期隨內核;
3.數據傳輸自帶優先級。

信號量
信號量用於實現進程間的控制,主要是同步和互斥。
本質:內核中的一個計數器(對資源進行計數) + pcb等待隊列

互斥的實現:經過只有 0 / 1 的計數器,實現對臨界資源訪問狀態的標記,在訪問臨界資源
以前先獲取信號量,計數 -1;若計數 <0 則使進程等待(將進程pcb加入隊列中);不然可
以對臨界資源進行訪問(而且在訪問期間,已經將臨界資源的狀態置爲不可訪問狀態,所以
可一保證其餘進程不會再訪問臨界資源。當前進程訪問完畢以後,則對計數進行+1,則喚醒
一個進程(將一個pcb出隊,置爲運行狀態)

同步的實現:信號量是一個對資源的計數,能夠經過計數判斷是否可以獲取一個資源進行處
理;若計數小於 0,則表示不能獲取(而且對計數進行 -1),須要等待(加入pcb隊列)。
這時候若其餘進程生產一個資源,則會對計數進行 +1,若計數 <= 0 ,則喚醒一個進程。
(負數表示正在等待進程的數量,若是爲正說明沒有進程須要資源)。

4、虛擬文件系統

Linux內核中的虛擬文件系統用一個通用的文件模型表示了各類不一樣的文件系統,這個文件模型屏蔽了不少具體文件系統的差別,使Linux內核支持不少不一樣的文件系統,這個文件系統能夠分爲邏輯文件系統和設備驅動程序:邏輯文件系統指Linux所支持的文件系統,例如ext二、ext3和fat等;設備驅動程序指爲每一種硬件控制器所編寫的設備驅動程序模塊。

5、網絡接口

網絡接口提供了對各類網絡標準的實現和各類網絡硬件的支持。網絡接口通常分爲網絡協議和網絡驅動程序。網絡協議部分負責實現每一種可能的網絡傳輸協議。網絡設備驅動程序則主要負責與硬件設備進行通訊,每一種可能的網絡硬件設備都有相應的設備驅動程序。
image
本羣免費分享學習資料(C/C++,Linux,golang,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,ffmpeg,TCP/IP,協程,DPDK,嵌入式)等,交流討論領取資料請加羣Q:1106675687。

相關文章
相關標籤/搜索