面試高頻題:進程之間的通信方式

面試高頻題:進程之間的通信方式

進程之間的通信方式,是面試的高頻試題,我就被騰訊的面試官Cue到了,簡單得列舉出各種方式,大部分同學都能回答上,但是你知道通信方式之間的區別與效率,不太清楚的,可以收藏本文,先收藏,後讀。

進程之間的通信方式

進程之間的通信方式,主要有一下幾種

  1. 管道,包括匿名管道、命名管道
  2. 信號
  3. 信號量
  4. 消息隊列
  5. 共享內存
  6. 本地套接字

管道

管道是一種半雙工的通信方式,數據只能單向流動

匿名管道

匿名管道只能在具有親緣關係的進程間使用,進程的親緣關係通常指父子進程關係

// 需要的頭文件
#include <unistd.h>

// 通過pipe()函數來創建匿名管道
// 返回值:成功返回0,失敗返回-1
// fd參數返回兩個文件描述符
// fd[0]指向管道的讀端,fd[1]指向管道的寫端
// fd[1]的輸出是fd[0]的輸入。
int pipe (int fd[2]);

使用匿名管道進行進程間的通信的過程,可以用下面例子說明

  • 父進程創建管道,得到兩個⽂件描述符指向管道的兩端
  • 父進程fork出子進程,⼦進程也有兩個⽂件描述符指向同⼀管道。
  • 父進程關閉fd[0],子進程關閉fd[1],即⽗進程關閉管道讀端,⼦進程關閉管道寫端(因爲管道只支持單向通信)。⽗進程可以往管道⾥寫,⼦進程可以從管道⾥讀,管道是⽤環形隊列實現的,數據從寫端流⼊從讀端流出,這樣就實現了進程間通信。

命名管道

不同於匿名管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存在於文件系統中。這樣,即使與FIFO的創建進程不存在親緣關係的進程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信(能夠訪問該路徑的進程與FIFO的創建進程之間通信),因此,通過FIFO不相關的進程也能交換數據。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀總是從開始處返回數據,對它們的寫則把數據添加到末尾。

信號

信號是一種比較複雜的通信方式,信號產生的條件:按鍵、硬件異常、進程調用kill函數將信號發送給另一個進程、用戶調用kill命令將信號發送給其他進程,信號傳遞的消息比較少,主要用於通知接收進程某個事件已經發生。

信號量

信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作爲一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作爲進程間以及同一進程內不同線程之間的同步手段。

消息隊列

消息隊列是消息的鏈表,存放在內核中並由消息隊列標識符標識,消息隊列克服了信號傳遞信息少,管道只能承載無格式字節流以及緩衝區大小受限等特點。消息隊列起信箱作用,到了就掛在那裏,需要的時候去取。消息隊列提供了一種在兩個不相關進程間傳遞數據的簡單有效的方法。與命名管道相比:消息隊列的優勢在於,它獨立於發送和接收進程而存在,這消除了在同步命名管道的打開和關閉時可能產生的一些困難。

共享內存

共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式(不需要從用戶態到內核態的切換),它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步和通信。

本地套接字

進程間通信的一種方式是使用UNIX套接字sockaddr_un,人們在使用這種方式時往往用的不是網絡套接字,而是一種稱爲本地套接字的方式。本地套接字用於本地進程間的通訊更安全和穩定。

使用套接字函數socket創建,不過傳遞的參數與網絡套接字不同。域參數應該是PF_LOCAL或者PF_UNIX,而不能用PF_INET之類。本地套接字的通訊類型應該是SOCK_STREAM或SOCK_DGRAM,協議爲默認協議。

創建了套接字後,還必須進行綁定才能使用。不同於網絡套接字的綁定,本地套接字的綁定的是struct sockaddr_un結構。struct sockaddr_un結構有兩個參數:sun_family、sun_path。sun_family只能是AF_LOCAL或AF_UNIX,而sun_path是本地文件的路徑。通常將文件放在/tmp目錄下。

本地套接字的其他操作都與網絡套接字相似。

參考文章

進程間通訊IPC的幾種方式總結

進程間8種通信方式詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章