1. 程式人生 > 程式設計 >程式間通訊方式總結

程式間通訊方式總結

前言

程式間的通訊方式,其實我們一直在用它,但是我們都不會去注意它。如果碰到面試官問你知道多少種程式間的通訊方式,估計很多人都會有點懵。今天我們就來總結下程式間的通訊方式有哪些。

管道

管道,英文為pipe。這是一個我們在學習Linux命令列的時候就會引入的一個很重要的概念。它的發明人是道格拉斯.麥克羅伊,這位也是UNIX上早期shell的發明人。他在發明瞭shell之後,發現系統操作執行命令的時候,經常有需求要將一個程式的輸出交給另一個程式進行處理,也因此,管道應運而生了。

管道可以分為兩類:匿名管道和命名管道。

常見的Linux命令 "|" 其實就是匿名管道,表示把一個程式的輸出傳輸到另外一個程式,如:

echo "Happyjava" | awk -F 'j' '{print $2}'
# 輸出 ava
複製程式碼

另外,我們可以通過 mkfifo <pipename> 命令建立一個命名管道,如:

mkfifo pipe
複製程式碼

一個程式往管道輸入資料,則會阻塞等待別的程式從管道讀取資料:

如果我另外一個視窗沒有執行 cat < pipe 命令,則左邊的視窗(echo 'Happyjava' > pipe)會一直阻塞。

訊息佇列

注意,此訊息佇列不是我們常用的MQ,如kafka,rabbitmq,rocketmq等。

訊息佇列提供了一種從一個程式向另一個程式傳送一個資料塊的方法。 每個資料塊都被認為含有一個型別,接收程式可以獨立地接收含有不同型別的資料結構。我們可以通過傳送訊息來避免命名管道的同步和阻塞問題。但是訊息佇列與命名管道一樣,每個資料塊都有一個最大長度的限制。

使用訊息佇列進行程式間通訊,可能會收到資料塊最大長度的限制約束等,這也是這種通訊方式的缺點。如果頻繁的發生程式間的通訊行為,那麼程式需要頻繁地讀取佇列中的資料到記憶體,相當於間接地從一個程式拷貝到另一個程式,這需要花費時間。

共享記憶體

共享記憶體這個通訊方式就可以很好著解決拷貝所消耗的時間了。系統載入一個程式的時候,分配給程式的記憶體並不是實際實體記憶體,而是虛擬記憶體空間。那麼我們可以讓兩個程式各自拿出一塊虛擬地址空間來,然後對映到相同的實體記憶體中,這樣,兩個程式雖然有著獨立的虛擬記憶體空間,但有一部分卻是對映到相同的實體記憶體,這就完成了記憶體共享機制了。

訊號量

共享記憶體最大的問題是什麼?沒錯,就是多程式競爭記憶體的問題,就像類似於我們平時說的執行緒安全

問題。如何解決這個問題?這個時候我們的訊號量就上場了。

訊號量的本質就是一個計數器,用來實現程式之間的互斥與同步。例如訊號量的初始值是 1,然後 a 程式來訪問記憶體1的時候,我們就把訊號量的值設為 0,然後程式b 也要來訪問記憶體1的時候,看到訊號量的值為 0 就知道已經有程式在訪問記憶體1了,這個時候程式 b 就會訪問不了記憶體1。所以說,訊號量也是程式之間的一種通訊方式。

Socket

這個就是我們一直在用的程式間的通訊方式了,如我們的微信APP跟微信伺服器通訊,其實就是使用的Socket套接字進行通訊的。

總結

這裡總結下,程式(Linux)間的通訊方式有:

1、管道

2、訊息佇列

3、共享記憶體

4、訊號量

5、Socket