程序通訊-管道

由於各個程序之間獨享一塊使用者地址空間,一般而言這塊獨立的使用者地址空間不能互相訪問,所以程序之間想要通訊必須透過核心空間(每個程序共享)。

程序間的通訊方式主要有以下幾種:

管道

訊息佇列

共享記憶體

訊號量

訊號

Socket

程序通訊-管道

管道

管道的資料傳輸方向是單向的,如果兩個程序之間需要互相傳遞資料,那麼需要建立兩個管道才可以。

管道主要分為:

匿名管道

命令管道

匿名管道

匿名管道只適合具有

父子關係的程序間

通訊,建立需要透過下面的系統呼叫來實現:

int pipe(int fd[2])

這裡表示建立一個匿名管道,並返回了兩個描述符,fd[0]是管道讀取端描述符,fd[1]是管道寫入端描述符。匿名管道只存在於記憶體中,不存在於檔案系統。

這裡的管道就是核心裡面的一串快取。

管道傳輸的資料無格式但是大小受限

父子程序間如何使用匿名管道通訊

我們需要透過fork來建立子程序,

建立的子程序會複製父程序的檔案描述符

,這樣父子程序之間都會有fd[0]和fd[1],父子程序透過各自的fd寫入和讀取同一個管道檔案就可以實現跨程序通訊。

由於父子程序都可以對管道進行讀寫,為了避免這種情況的發生,通常我們會做以下操作:

父程序關閉讀取的fd[0],只保留寫入的fd[1]

子程序關閉寫入的fd[1],只保留讀取的fd[0]

程序通訊-管道

所以如果需要進行雙向通訊,必須要建立兩個管道。

shell中的A|B管道操作有什麼特別?

ps aux | grep mysql

Linux上述命令|是一個管道,它的功能是將前一個命令的輸出當做後一個命令的輸入。但是在執行上述命令(A|B)時,由於A程序和B程序都是由shell創建出來程序,A和B之間不存在父子關係,它們父程序都是shell。它的管道讀寫圖如下:

程序通訊-管道

命名管道

命名管道可以在不相關的程序之間能互相通訊

,因為命令管道需要提前建立一個型別為管道的裝置檔案,在程序裡只要使用這個裝置檔案,就可以互相通訊。

建立管道檔案

mkfifo test_pipe

程序通訊-管道

向管道寫入資料

echo “hello pipe” > test_pipe

程序通訊-管道

在寫入資料以後,命令停在此處,是因為管道里的內容沒有被讀取,只有當管道里的命令被讀取以後,命令才可以正常退出。

讀取管道命令

cat test_pipe

程序通訊-管道

可以看到在執行cat讀取命令以後,內容被讀取出來列印在終端上,另一方面寫入指令echo也正常退出。