目前linux進程間通信的常用方法是什麼(pipe?信號量?消息隊列?)?


PIPE和FIFO用來實現進程間相互發送非常短小的、頻率很高的消息;這兩種方式通常適用於兩個進程間的通信。

共享內存用來實現進程間共享的、非常龐大的、讀寫操作頻率很高的數據(配合信號量使用);這種方式通常適用於多進程間通信。

其他考慮用socket。這裡的「其他情況」,其實是今天主要會碰到的情況:分散式開發。在多進程、多線程、多模塊所構成的今天最常見的分散式系統開發中,socket是第一選擇

消息隊列,現在建議不要使用了 ---- 因為找不到使用它們的理由。

在實際中,我個人感覺,PIPE和FIFO可以偶爾使用下,共享內存都用的不多了。在效率上說,socket有包裝數據和解包數據的過程,所以理論上來說socket是沒有PIPE/FIFO快,不過現在計算機上真心不計較這麼一點點速度損失的。你費勁糾結半天,不如我把socket設計好了,多插一塊CPU來得更划算。

另外,進程間通信的數據一般來說我們都會存入資料庫的,這樣萬一某個進程突然死掉或者整個伺服器死了,也不至於丟失重要數據、便於回滾到之前的狀態。從這個角度考慮,適用共享內存的情況也更少了,所以socket使用得更多。

再多說一點關於共享內存的:共享內存的效率確實高,但它的重點在「共享」二字上。如果的確有好些進程共享一大塊數據(如果把每個進程都看做是類的對象的話,那麼共享數據就是這個類的static數據成員),那麼共享內存就是一個不二的選擇了。但是在面向對象的今天,我們更多的時候是多線程+鎖+線程間共享數據。因此共享進程在今天使用的也越來越少了。

不過,在面對一些極度追求效率的需求時,共享內存就會成為唯一的選擇,比如高頻交易系統。除此以外,一般是不需要特意使用共享內存的。

另外,PIPE和共享內存是不能跨LAN的(FIFO可以)如果你的分散式系統隨著需求的增加而越來越大所以你想把不同的模塊放在不同機器上而你之前開發的時候用了PIPE或者共享內存,那麼你將不得不對代碼進行大幅修改......同時,即使FIFO可以跨越LAN,其代碼的可讀性、易操作性和可移植性、適應性也遠沒有socket大。這也就是為什麼一開始說socket是第一選擇的原因。

最後還有個信號簡單說一下。

請注意,是信號,不是信號量。信號量是用於同步線程間的對象的使用的(建議題主看我的答案,自認為比較通俗易懂:semaphore和mutex的區別? - Linux - 知乎)。

信號也是進程間通信的一種方式。比如在Linux系統下,一個進程正在執行時,你用鍵盤按Ctrl+c,就是給這個進程發送了一個信號。進程在捕捉到這個信號後會做相應的動作。

雖然信號是可以自定義的,但這並不能改變信號的局限性:不能跨LAN、信息量極其有限

在現代的分散式系統中,通常都是消息驅動:即進程受到某個消息後,通過對消息的內容的分析然後做相應的動作。如果你把你的分散式系統設置成信號驅動的,這就表示你收到一個信號就要做一個動作而一個信號的本質其實就是一個數字而已。這樣系統稍微大一點的話,系統將變得異常難以維護;甚至在很多時候,信號驅動是無法滿足我們的需求的。

因此現在我們一般也不用信號了。

因此,請記住:除非你有非常有說服力的理由,否則請用socket。

順便給你推薦個基於socket的輕量級的消息庫:ZeroMQ。


System V IPC 幾乎已經沒人用了。

除了有特定性能需求的情況下,現在常見都是基於 socket ,包括 PF_UNIX 和 PF_INET 127.0.0.1。有些情況會選用基於文件系統的 unix socket (mkfifo)。

希望使用高層一些的協議可以考慮 Thrift, Protobuf, MessagePack 或 0mq 等方案。


socket,桌面版本還有dbus,這個用的特別多。


按需定製的解決方案,無從定義常用方法


推薦閱讀:

LocalMQ:從零構建類 RocketMQ 高性能消息隊列
Kafka,Mq,Redis作為消息隊列使用時的差異?

TAG:Linux | 消息隊列 |