管道的應用

一、跨越fork調用的管道(在不同進程之間進行讀寫操作)

管道的真正優勢體現在,當你想在兩個進程之間傳遞數據的時候。當程序用fork調用創建新進程時,原先打開的文件描述符仍將保持打開狀態,如果在原先的進程中創建一個管道,然後再調用fork創建新進程,我們即可通過管道在兩個進程之間傳遞數據。

代碼實現:

  #include<unistd.h>
  #include<stdlib.h>
  #include<stdio.h>
  #include<string.h>
  #define BUFSIZE 128
  
  int main()
  {
      int data_processed;
      int file_pipes[2];
      const char some_data[] = "123";
      char buffer[BUFSIZE];
      pid_t fork_result;
  
      memset(buffer,'\0',sizeof(buffer));
  
      if(pipe(file_pipes) == 0)
      {
          fork_result = fork();
          if(fork_result == -1)
          {
              fprintf(stderr,"FORK failure");
              exit(EXIT_FAILURE);
          }
          //在確認fork調用成功後,如果fork_result等於零,就說明我們是在子進程中
          if(fork_result == 0)
          {
              data_processed = read(file_pipes[0],buffer,BUFSIZE);
              printf("Read %d bytes: %s\n",data_processed, buffer);
              exit(EXIT_SUCCESS);
          }
          else  //否則,肯定是在父進程中
          {
              data_processed = write(file_pipes[1],some_data,strlen(some_data));
              printf("Wrote %d bytes\n",data_processed);
          }
      }
      exit(EXIT_SUCCESS);
  }

結果展示:

這個程序首先用pipe調用創建一個管道,接着用fork調用創建一個新進程。如果fork調用成功,父進程就寫數據到管道中,而子進程從管道中讀取數據。父進程都在只調用了一次write或read之後就退出。如果父進程在子進程之前退出,你就會在兩部分輸出內容之間看到shell提示符。

下面給出圖示幫助理解:

                                            

二、父進程和子進程

在接下來的對pipe調用的研究中,我們將討論如何在子進程中運行一個與其父進程完全不同的另外一個程序,而不是僅僅運行一個相同程序,我們將使用exec調用來完成這一工作,這裏有一個難點是通過exec調用的進程需要知道應該訪問哪個文件描述符,上面的例子中,因爲進程本身有file_pipes數據的一份副本,所以這並不成爲問題,但經過exec調用後,情況就不一樣了,因爲原先的進程已經被新的子進程替換了,爲解決這個問題,我們可以將文件描述符(它實際上只是一個數字)作爲一個參數傳遞給exec啓動的程序,爲方便演示它是如何工作的,我們需要使用兩個程序,第一個程序是數據生產者,它負責創建管道和啓動子進程,而後者是數據消費。

代碼實現:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#define BUFSIZE 128
int main()
{
     int data_processed;
     int file_pipes[2];
     const char some_data[] = "123";
     char buffer[BUFSIZE];
     pid_t fork_result;
 
     memset(buffer,'\0',sizeof(buffer));
 
     if(pipe(file_pipes) == 0)
     {
         fork_result = fork();
         if(fork_result == -1)
         {
             fprintf(stderr,"Fork failure");
             exit(EXIT_FAILURE);
         }
 
         if(fork_result == 0)
         {
             sprintf(buffer,"%d",file_pipes[0]);
             (void)execl("pipe4.c","pipe4.c",buffer,(char *)0);
             exit(EXIT_FAILURE);
         }
         else
         {
             data_processed = write(file_pipes[1],some_data,strlen(some_data));
             printf("%d - wrote %d bytes\n",getpid(),data_processed);
         }
     }
     exit(EXIT_SUCCESS);
 }

(2)數據消費者程序pipe4.c負責讀取數據

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章