程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 一起talk C栗子吧(第八十八回:C語言實例--使用管道進行進程間通信一)

一起talk C栗子吧(第八十八回:C語言實例--使用管道進行進程間通信一)

編輯:關於C語言

一起talk C栗子吧(第八十八回:C語言實例--使用管道進行進程間通信一)


各位看官們,大家好,上一回中咱們說的是使用管道進行進程間通信概述的例子,這一回咱們說的例子是:使用第一種管道進行進程間通信。閒話休提,言歸正轉。讓我們一起talk C栗子吧!

我們在上一回中介紹了三種管道,這一回中我們介紹第一種管道(偽管道)及其使用方法。主要是讓大家明白如何使用管道進行進程間的通信。

第一種管道我稱之為偽管道。在介紹它之前,我們先介紹兩個函數:popen和pclose

popen函數的原型

FILE * popen(const char * command, const char *open_mode)
第一個參數是一個字符串。可以依據程序需要來傳入相關的字符串; 第二個參數是打開管道的方式。只能在r和w中選擇一種打開方式。r/w表示從管道中讀/寫數據; 該函數返回文件流指針,因此,我們可以像操作文件一樣操作它,常用的函數是fread/fwrite.

大家可以看到,該函數通過用來打開一個管道,然後在進程中操作管道。函數的第一個參數是一個字符串,我們可以給它傳遞各種Linux終端命令,而Linux命令可以啟動相關的進程,這樣就可以在進程中操作管道了,常用的操作是傳遞數據。

pclose函數的原型

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      //命令運行的結果

大家和上面的程序運行結果對比一下就會發現,它們的運行結果完全一致。

看官們,正文中就不寫代碼了,詳細的代碼放到了我的資源中,大家可以點擊這裡下載使用。

各位看官,關於使用管道進行進程間通信的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved