各位看官們,大家好,上一回中咱們說的是使用管道進行進程間通信概述的例子,這一回咱們說的例子是:使用第一種管道進行進程間通信。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
我們在上一回中介紹了三種管道,這一回中我們介紹第一種管道(偽管道)及其使用方法。主要是讓大家明白如何使用管道進行進程間的通信。
第一種管道我稱之為偽管道。在介紹它之前,我們先介紹兩個函數:popen和pclose。
FILE * popen(const char * command, const char *open_mode)
第一個參數是一個字符串。可以依據程序需要來傳入相關的字符串; 第二個參數是打開管道的方式。只能在r和w中選擇一種打開方式。r/w表示從管道中讀/寫數據; 該函數返回文件流指針,因此,我們可以像操作文件一樣操作它,常用的函數是fread/fwrite.
大家可以看到,該函數通過用來打開一個管道,然後在進程中操作管道。函數的第一個參數是一個字符串,我們可以給它傳遞各種Linux終端命令,而Linux命令可以啟動相關的進程,這樣就可以在進程中操作管道了,常用的操作是傳遞數據。
int pclose(FILE *stream )
該函數只有一個參數,它是一個文件流類型的指針,表示需要關閉的文件流; 該函數返回值為參數指向的流所在進程結束時的退出碼。
大家可以看到,該函數常用來關閉popen函數打開的管道,因此需要與popen函數配合使用,而且經常被用在進程結束的時候。
明白這兩個函數及其用法後,我們接下來介紹偽管道的使用方法,詳細內容如下:
1.使用popen函數打開一個管道,打開方式依據需要指定,只能指定為r或者w; 2.使用函數fread/fwrite從管道中讀/寫數據; 3.使用pclose函數關閉步驟1中打開的管道。我們接下來使用具體的例子進行說明,下面是詳細的代碼:
int main()
{
char buffer[BUFSIZ+1];
int read_count = 0;
FILE *p_read,*p_write;
memset(buffer,'\0',sizeof(buffer));
p_read = popen("env","r"); //打開管道
if(NULL == p_read)
{
printf("open pipe for reading failed \n");
return 1;
}
p_write = popen("grep bash","w"); //打開管道
if(NULL == p_write)
{
printf("open pipe for writing failed \n");
return 1;
}
read_count = fread(buffer,sizeof(char),BUFSIZ,p_read);
while(read_count > 0)
{
fwrite(buffer,sizeof(char),strlen(buffer),p_write);
read_count = fread(buffer,sizeof(char),BUFSIZ,p_read);
}
pclose(p_read); //關閉管道
pclose(p_write); //關閉管道
return 0;
}
從上面的代碼中可以看到,我們通過在popen函數中傳遞env和grep和這兩個Linux命令來啟動兩個進程,這兩個進程都對管道進行了相關的操作:
env命令啟動的進程在管道中存放了數據,數據的內容就是env命令的運行結果; grep命令啟動了的進程從管道中讀取env命令所在進程存放的數據,並且輸出結果。關於popen函數中使用的r/w打開方式,有些看官有疑問:env啟動的進程在管道中存放數據,應該使用寫的方式打開管道,怎麼使用讀的方式打開呢?我給大家解釋一下程序的運行過程,大家就能明白其中的原因了:
為了方便解釋,我們假設main函數所在的進程為A,env啟動所在的進程為B,grep啟動的進程為C。 進程A以讀的方式打開了管道並且啟動進行B,讀方式表示進程A可以從進程B中讀取內容,這些內容正是進程B的輸出。 進程A讀取這些內容後存放到了管道中。 類似地,進程A以寫的方式打開了管道並且啟動進行C,寫方式表示進程A可以向從進程C中寫入內容,這些內容正是進程A存放到了管道中的數據。 進程C把從管道中讀取這些數據後,並且對數據進行處理,進而輸出處理的結果,也就是進程A運行的結果。通過這麼分析以後,大家可以明白地看到,進程之間如何使用管道傳送數據,進而實現了進程之間的通信。
下面是程序的運行結果,請大家參考:
./s //運行編譯後的程序
SHELL=/bin/bash //顯示程序輸出的結果
我們說過,這種管道是一種偽管道,因為popen的參數是某個Linux命令,而且它是通過啟動shell來執行Linux命令。它的效果和終端中管道命令“|”的效果相同。
下面是在Linux終端中使用管道的結果:
env | grep bash //在終端中輸入該命令並且 運行
SHELL=/bin/bash //命令運行的結果
大家和上面的程序運行結果對比一下就會發現,它們的運行結果完全一致。
看官們,正文中就不寫代碼了,詳細的代碼放到了我的資源中,大家可以點擊這裡下載使用。
各位看官,關於使用管道進行進程間通信的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。