Hey,Guys! 給我發條消息吧?

我們知道,無論是在進程互斥還是進程同步中,所有的進程都交換了消息——一個簡單的喚醒信號。
雖然只是一個簡單的消息,但我們依舊可以將其劃分到進程通信中,作為一種低級通信看待(蚊子再小也是肉嘛!)。
有低級通信,那自然也就有高級通信,不過一般而言,我們所說的進程通信都是指高級通信,畢竟互斥和同步都有自己專屬的稱呼。

進程通信


進程間的互斥,同步以及信息交換統稱為進程通信

進程通信的模式

  1. 共享內存模式

    • 相互通信的進程之間有公共內存,這個公共內存是操作系統分配和管理的,而其使用和基於此的信息傳遞則是相互通信的進程自己完成的。
    • 由於是基於公共內存,故而對其訪問需要提供必要的同步機制(等價於共享變量)。

      小的時候做過一個傳聲器,兩個紙杯加上一根繩子就可以製作了,但問題就是兩個紙杯共用一根繩子,我和朋友只能是一個說,一個聽,要不然就聽不到對方再說什麼了。

  2. 消息傳遞模式
     
    在此種模式下的信息傳遞是不需要公共內存的。操作系統提供提供發送命令(send)和接收命令(receive)這兩個系統調用命令來進行消息傳遞(通信)。

    發生消息傳遞時,只需通信的進程調用這兩個命令即可。由於這兩個命令是由操作系統提供的,所以命令內部的實現對於用戶是透明的。
    就像我們打電話,只需要會打電話,會接電話就好了,除了研究這個技術的人,誰會關心怎麼實現的這個技術呢?

基於消息傳遞的實現

直接方式

在這種方式下,進程會直接指定消息源或者接受方,類似於函數的映射,有一對一和多對一的類型。

  • 一對一,即對稱形式


    對稱形式
  • 多對一,即非對稱形式


    非對稱形式

    高中學數學,最痛苦的就是函數的映射關係,開始的時候一看,哎呀,挺簡單的,理解了,然後老師上課提問映射的關係……
    咦?映射,什麼玩意兒?!
    渾渾噩噩一個學期之後,什麼1-1映射,慢射之類的,還是挺模糊的,不懂,於是就聽同桌說,畫個函數圖像啦,balabala一堆之後,終於懂了。
    於是整個高中三年,遇到映射就畫個圖像……

消息傳送的途經

  1. 帶緩衝的途經
    高級語言進行文件讀寫的時候似乎都有帶緩衝和不帶緩衝的讀寫?帶緩衝流程序開銷小,這是由於不需要頻繁的進入磁盤讀取文件,進程的消息傳遞也是這樣的。


    帶緩衝的send和receive的具體實現

    send和receive命令都是操作系統提供的,使用的時候是要進入操作系統的,而這兩者進入操作系統是靠進程產生的自願性中斷實現的。而且有個緩衝區,只需中斷一次,讀取完消息,回到用戶態就可以繼續向下執行其他的程序,不用不斷的中斷讀取,直到讀取完畢。

  2. 不帶緩衝


    不帶緩衝的send和receive的具體實現

    這看其來可比帶緩衝的簡單太多了,而且沒有了緩衝區,也就節省了空間,但是由於要等待接收進程完成消息接收后才能讓發送進程繼續推進,這樣看來併發性着實太弱了。

間接方式

間接方式和直接方式相對應,是存在媒介進行信息的交換——通信,不需要指明進程具體是哪一個,只需要指明相互通信的進程使用的中間媒介。
這个中間媒介在操作系統中被描述為信箱,所以間接方式也成為信箱方式,在實現這種方式時,信箱既可以屬於操作系統空間,也可以是屬於用戶進程空間,但關於信箱操作的命令則是操作系統提供的(系統調用命令),屬於操作系統,來看看關於信箱的定義:

typedef struct mailbox
{
    int in, out;      //讀寫內容的位置,初始為0
    int k;      //消息的個數
    semaphore s1, s2;     //協調發送和接收的信號量初始為k和0
    semaphore mutex;    //用於各進程進入信箱的互斥
    message letter[k];         //信箱,保存k個消息
}MailBox;

對於信箱的操作定義:

send_MB(MailBox A, message M)
{
    P(A.s1);
    P(A.mutex);
    A.letter[A.in] = M;
    A.in = (A.in + 1) % A.k;
    V(A.mutex);
    V(A.s2);
}

receive_MB(MailBox A, message N)
{
    P(A.s2);
    P(A.mutex);
    N = A.letter[A.out];
    A.out = (A.out + 1) % A.k;
    V(A.mutex);
    V(A.s1);
}

send_MB和receive_MB只是關於信箱的四個命令之一,因為還要創建和刪除嘛!


信箱命令的使用權限

話說,朋友之間吵架冷戰算是很正常的事情吧?
我上高中那會兒和同桌不知道因為啥原因吵了一架,然後就開始冷戰,到後來一次班上六人一組討論問題(我們開玩笑說這是圓桌會議),關於一個問題又出現分歧,然後我就伸手隨便拉住某個人說:“她是不是傻!alabala…..”,我同桌又拽着他:“你告訴他,這麼簡單的邏輯問題都出錯,明顯是他傻!”……
想想那兄弟可能也挺無奈的,你說兩人都能聽到對方說話,還非要找第三人來當傳聲筒……

小結


在進程通信的模式選擇上,沒有完美,只有適合於不適合,即便我們說無緩衝的通信併發性差,開銷還大,但是耐不住人家實現簡單啊,在一些簡單的問題實現上和帶緩衝的通信差距並不大,那為何要選擇帶緩衝的通信方式呢?殺雞焉用牛刀?
這條經驗,不僅僅適用於進程通信上,幾乎什麼事情,這條經驗都是實用的。

Hey! Guys! 我發了條消息給你,收到了嗎?