程序通訊 1 管道

2021-08-30 13:31:15 字數 2372 閱讀 5357

程序之間通訊的方式有很多種,主要包括

管道命名管道

訊號訊息佇列

共享記憶體

訊號量套接字

其中,管道是最早的一種程序間通訊機制,主要適用於具有親緣關係之間的程序間通訊,比如,父程序與子程序之間,或者同乙個父程序的兩個子程序之間。同時,管道是一中半雙工的通訊,資料只能單向流動,從一段寫入,另外一段讀出。下面通過幾個例子來看一下管道如何使用。

#include int pipe(int fd[2]);
pipe函式建立乙個管道,其宣告在unistd.h當中,傳入引數是乙個int[2]陣列,返回值如果為0表示,pipe建立成功,同時fd陣列中儲存兩個檔案描述符,fd[1]指向管道的寫端,fd[0]指向管道的讀端;如果小於0,表示建立失敗。

下面看乙個最簡單的例子

#include#includeint main()

write(fd[1], "hello world\n", 12);

n = read(fd[0], buf, 1024);

printf("%s",buf);

return 0;

}

上面的**很簡單,就是建立了乙個管道,然後向寫端寫入「hello world\n」字串,然後從讀端讀出,儲存到buf陣列中,最後列印到螢幕。這個例子可以用下面的示意圖來表示:

管道像一根單向的水管,資料像水一樣從一端流入,從另一端流出。管道也是有緩衝空間的,如果一直寫入不讀取,那麼緩衝空間會被佔滿,再往裡面寫資料就會失敗(就像水管的流出端被關閉,水不能再流入一樣),同樣的,如果唯讀不寫,那麼資料被讀完之後,就沒有東西可讀了,再次讀取也會失敗。這個例子顯然是沒什麼用途的,但是可以幫助我們理解什麼是管道。

再來看第二個例子

#include#includeint main()

// 建立子程序

if ((pid = fork()) < 0) else if (pid == 0) else

}return 0;

}

第二個例子比第乙個例子稍微複雜了一些。首先,父程序建立了乙個管道,然後fork出乙個子程序。在子程序中讀取管道內容,並列印內容,然後返回結束程序;在父程序中向管道寫入字串,然後等待子程序結束,最後結束程序。這個例子可以用下面的圖來表示

執行fork之後,主程序建立了乙個子程序,子程序完全複製父程序的虛擬記憶體空間(這個說法其實不嚴謹,見後文),同時繼承父程序開啟的檔案等資源,所以兩個描述符也被繼承下來,兩個程序的fd陣列具有相同的值,並且指向同樣的pipe埠。因此,父子程序之前可以通過pipe實現通訊。一般地,我們會在pipe寫入端程序關閉讀端,在pipe讀入端關閉寫端。在上面的**中,加入兩行

#include#includeint main()

// 建立子程序

if ((pid = fork()) < 0) else if (pid == 0) else

}return 0;

}

那麼程序模型變成這樣

第三個例子,我們把子程序的標準輸入重定向到管道的讀埠

#include#includeint main()

if ((pid = fork()) < 0) else if (pid == 0)

// 重定向成功的話,那麼讀端就有了兩個檔案描述符,

//分別是stdin_fileno和fd[0],此時可以關閉fd[0],保留stdin_fileno即可

close(fd[0]);

}//此時可以通過stdin_fileno讀取管道內容

n = read(stdin_fileno, buf, 1024);

printf("%s",buf);

} else

}return 0;

}

tips:主程序建立了乙個子程序,子程序完全複製父程序的虛擬記憶體空間這個說法其實是不嚴謹的,父子程序的**段實際上是共用的,另外完全複製父程序的虛擬記憶體空間,會造成時間和記憶體上的浪費,有的時候根本沒有必要完全複製,因此出現了cow(copy on write)技術,也就是「寫時複製」,就是當子程序對某個變數進行寫操作時,才進行複製。這個技術對使用者程式是不可見的,因此,在使用者程式層面上,認為子程序完全複製父程序的虛擬記憶體空間是完全沒有問題的。

程序通訊1 管道通訊

管道是單向的 先進先出的,它把乙個程序的輸出和另乙個程序的輸入連線在一起。乙個程序 寫程序 在管道尾部寫入資料,另乙個程序 讀程序 從管道的頭部讀出資料。兩個程式之間傳遞資料的一種簡單方法是使用popen和pclose。include file popen const char command,co...

程序通訊1 管道 命名管道

匿名管道 管道是一種簡單的程序通訊 ipc 機制。管道實質上就是pipe函式在核心中開闢了一段緩衝區,有乙個讀端和乙個寫端。兩個程序之間能夠通訊的本質 通過fork函式傳遞檔案描述符 子程序是父程序的副本,父程序所有開啟的檔案描述符都被複製到子程序中,父子程序的每個相同的開啟描述符共享乙個檔案表項 ...

程序間通訊(1) 管道

linux下一切皆檔案,我們可以建立乙個管道檔案進行通訊,實際上是呼叫pipe函式在核心中開闢一塊緩衝區 稱為管道 用於通訊,管道是一種最基本的ipc機制,由pipe函式建立 include int pipe int filedes 2 它有乙個讀端乙個寫端,然後通過filedes引數傳出給使用者程...