FILE*popen(constchar*command,//是要運行的程序名和相應的參數constchar*open_mode//必須是“r”或者“w”,如果是其它值,errno將返回EINVAL);intpclose(FILE*stream_to_close);popen()函數通過創建一個管道,調用fork產生一個子進程,執" />

日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Linux學習筆記24——進程管道

系統 2115 0

一 管道的作用

  通常把一個進程的輸出通過管道連接到另一個進程的輸入。

二 popen和pclose函數

      #include <stdio.h>
      
        



FILE 
      
      *popen(
      
        const
      
      
        char
      
       *command,
      
        
          //是要運行的程序名和相應的參數
        
        
       const
char * open_mode      //必須是“r”或者“w”,如果是其它值,errno將返回EINVAL
       );                 
int pclose(FILE *stream_to_close);     

  popen() 函數通過創建一個管道,調用 fork 產生一個子進程,執行一個 shell 以運行命令來開啟一個進程。

  pclose()調用只在popen啟動的進程結束后才返回,如果調用pclose函數時它仍在運行,pclose調用將等待該進程的結束。

例:

      #include <stdio.h>
      
        

#include 
      
      <stdlib.h>
      
        

#include 
      
      <unistd.h>
      
        

#include 
      
      <
      
        string
      
      .h>




      
        int
      
      
         main(){

    FILE 
      
      *
      
        read_fp;          
        
          //要讀取的文件描述符 
        
      
      
        char
      
       buffer[BUFSIZ+
      
        1
      
      
        ];      
        
          //用來存儲讀到的文件信息 
        
      
      
        int
      
      
         chars_read;          
        
          //實際讀取的元素個數
        
        

    

    memset(buffer,
      
      
        '
      
      
        \0
      
      
        '
      
      ,
      
        sizeof
      
      
        (buffer));    
        
          //將數組清零初始化
        
        

    read_fp
      
      =popen(
      
        "
      
      
        cat test*.c | wc -l
      
      
        "
      
      ,
      
        "
      
      
        r
      
      
        "
      
      
        );  
        
          //創建管道,用于顯示所有test*.c文件的字數 
        
      
      
        if
      
      (read_fp!=
      
        NULL){

        chars_read
      
      =fread(buffer,
      
        sizeof
      
      (
      
        char
      
      
        ),BUFSIZ,read_fp);
        
          //從一個文件流中讀數據,最多讀取count個元素,每個元素size字節,如果調用成功返回實際讀取到的元素個數,如果不成功返回 0 
        
      
      
        while
      
      (chars_read>
      
        0
      
      
        ){

            buffer[chars_read
      
      -
      
        1
      
      ]=
      
        '
      
      
        \0
      
      
        '
      
      
        ;      
        
          //清除回車符
        
        

            printf(
      
      
        "
      
      
        Reading:-\n %s\n
      
      
        "
      
      
        ,buffer);

            chars_read
      
      =fread(buffer,
      
        sizeof
      
      (
      
        char
      
      
        ),BUFSIZ,read_fp);

        }

        pclose(read_fp);        
        
          //關閉管道
        
        

        exit(EXIT_SUCCESS);

    }

    exit(EXIT_FAILURE);

}
      
    

  使用shell的一個不太好的影響:針對每個popen調用,不僅要啟動一個被請求的程序,還要啟動一個shell,即每個popen調用將多啟動兩個進程。從節省系統資源的角度來看,popen函數的調用成本略高,而且對目標命令的調用比正常方式要慢一些。

三 pipe函數

      #include <unistd.h>


      
        int
      
       pipe(
      
        int
      
       fd[
      
        2
      
      ]);
    

  pipe函數的參數是一個由兩個整數類型的文件描述符組成的數組的指針,兩個返回的文件描述符以一種特殊的方式連接起來,寫到fd[1]的所有數據都可以從fd[0]讀回來,數據基于先進先出的原則(FIFO)進程處理。

  對一個已關閉寫數據的管道做read調用將返回0而不是阻塞,讀取無效的文件描述符將看作是一個錯誤并返回-1
?
  如果跨越fork調用使用管道,就會有兩個不同的文件描述符可以用于向管道寫數據,一個在父進程中,一個在子進程中。只有把父子進程中的針對管道的寫文件描述符都關閉,管道才會被認為是關閉了,對管道的read調用才會失敗。

管道的讀寫規則:

  1 從管道中讀取數據

  • 如果管道的寫端不存在,則認為已經讀到了數據的末尾,讀函數返回的讀出字節數為0;
  • 當管道的寫端存在時,如果請求的字節數目大于PIPE_BUF,則返回管道中現有的數據字節數,如果請求的字節數目不大于 PIPE_BUF,則返回管道中現有數據字節數(此時,管道中數據量小于請求的數據量);或者返回請求的字節數(此時,管道中數據量不小于請求的數據 量)。注:(PIPE_BUF在include/linux/limits.h中定義,不同的內核版本可能會有所不同。Posix.1要求 PIPE_BUF至少為512字節,red hat 7.2中為4096)。

  2 從管道中寫入數據

  向管道中寫入數據時,linux將不保證寫入的原子性,管道緩沖區一有空閑區域,寫進程就會試圖向管道寫入數據。如果讀進程不讀走管道緩沖區中的數據,那么寫操作將一直阻塞。
  注:只有在管道的讀端存在時,向管道中寫入數據才有意義。否則,向管道中寫入數據的進程將收到內核傳來的SIFPIPE信號,應用程序可以處理該信號,也可以忽略(默認動作則是應用程序終止)。

?

例子:

      #include <stdio.h>
      
        

#include 
      
      <stdlib.h>
      
        

#include 
      
      <unistd.h>
      
        

#include 
      
      <
      
        string
      
      .h>




      
        int
      
      
         main(){

    
      
      
        const
      
      
        char
      
       some_data[]=
      
        "
      
      
        123
      
      
        "
      
      
        ;

    
      
      
        int
      
       file_pipes[
      
        2
      
      
        ];

    
      
      
        int
      
      
         data_processed;

    pid_t fork_result;

    

    
      
      
        if
      
      (pipe(file_pipes)==
      
        0
      
      
        ){

        fork_result
      
      =
      
        fork();

        
      
      
        if
      
      (fork_result==(pid_t)-
      
        1
      
      
        ){

            fprintf(stderr,
      
      
        "
      
      
        Fork failure
      
      
        "
      
      
        );

            exit(EXIT_FAILURE);

        }

        
      
      
        if
      
      (fork_result==
      
        0
      
      
        ){      
        
          //子進程
        
        

            close(
      
      
        0
      
      
        );         
        
           //關閉標準輸入,即鍵盤輸入
        
        

            dup(file_pipes[
      
      
        0
      
      
        ]);    
        
          //復制一個文件描述符
        
        

            close(file_pipes[
      
      
        0
      
      
        ]);   ?
        
          //關閉讀操作
        
        

            close(file_pipes[
      
      
        1
      
      
        ]);   
        
          //關閉寫操作
        
        

            

            execlp(
      
      
        "
      
      
        od
      
      
        "
      
      ,
      
        "
      
      
        od
      
      
        "
      
      ,
      
        "
      
      
        -c
      
      
        "
      
      ,(
      
        char
      
      *)
      
        0
      
      
        );  
        
          //利用od查看特殊格式的文件內容,-c表示ASCII字符或反斜杠序列,(char*)0參數作用是終止被調用程序的參數列表
        
        

            exit(EXIT_FAILURE);

        }

        
      
      
        else
      
      
        {    
        
           //主進程
        
        

            close(file_pipes[
      
      
        0
      
      
        ]);  

            data_processed
      
      =write(file_pipes[
      
        1
      
      
        ],some_data,strlen(some_data));  
        
          //寫入數據
        
        

            close(file_pipes[
      
      
        1
      
      
        ]);

            printf(
      
      
        "
      
      
        %d - wrote %d bytes\n
      
      
        "
      
      
        ,getpid(),data_processed);

        }

    }

    exit(EXIT_SUCCESS);

}
      
    

?

?

?

Linux學習筆記24——進程管道


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 大埔区| 高碑店市| 文水县| 志丹县| 化德县| 定远县| 资中县| 兴山县| 巴彦县| 晋州市| 天气| 英山县| 北京市| 镇江市| 体育| 轮台县| 潢川县| 榆树市| 共和县| 常德市| 长顺县| 宜君县| 中宁县| 通辽市| 南皮县| 南康市| 通山县| 邵阳市| 宁德市| 平舆县| 新宁县| 屏南县| 丰原市| 彭山县| 囊谦县| 吉安县| 平利县| 余姚市| 武安市| 韶山市| 于田县|