如圖片顯示異常請前往掘金查看:https://juejin.im/post/5d515c7551882511ed7c273c
前言
進程間的通信方式,其實我們一直在用它,但是我們都不會去注意它。如果碰到面試官問你知道多少種進程間的通信方式,估計很多人都會有點懵。今天我們就來總結下進程間的通信方式有哪些。
管道
管道,英文為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