IPC 進程間通訊方式——管道

進程間通訊概述

  • 數據傳輸:一個進程須要將它的數據發送給另外一個進程,發送的數據量在一個字節到幾兆字節之間
  • 共享數據:多個進程想要操做共享數據,一個進程對共享數據的修改,別的進程應該馬上看到。
  • 通知時間:一個進程須要向另外一個或一組進程發送消息,通知他們發生了某些事件(如進程終止時要通知父進程)
  • 資源共享:多個進程之間共享一樣的資源,爲了作到這一點,須要內核提供鎖和同步機制
  • 進程控制:有些進程但願徹底控制另外一個進程的執行(如Debug進程),此時控制進程但願可以攔截另外一個進程的全部陷入的異常,並可以及時指導它的狀態改變。
 

進程間通訊方式

  • 管道(pipe),有名管道(FIFO)
  • 信號(signal)
  • 消息隊列
  • 共享內存
  • 信號量
  • 套接字(socket)
 

管道

  • 管道針對本地計算機的兩個進程之間的通訊而設計的通訊方式,管道創建後,實際得到兩個文件描述符:一個用於讀取另外一個用於寫入。
  • 常見的IPC機制,經過pipe系統調用。
  • 管道單工,數據只能向一個方向流動。雙向通訊時,須要創建兩個管道。
  • 數據的讀出和寫入:一個進程向管道中寫的內容被管道另外一端的進程讀出。寫入的內容每次都添加在管道的緩衝區的尾部,每次都是從緩衝區的頭部讀出數據。
 

管道的分類

  • 匿名管道 
    • 關係進程,父子或兄弟
    • 由pipe系統調用,管道由父進程創建
    • 管道位於內核空間,實際上是一塊緩存
  • 有名管道(FIFO) 
    • 兩個沒有任何關係的進程之間通訊可經過有名管道進行數據傳輸
    • 經過系統調用mkfifo建立
 

管道建立

 
  1. #include<unistd.h>
  2. int pipe(int fd[2]);
  3. //返回:0成功,-1出錯
  • 兩個文件描述符數組 
    • fd[0]:pipe的讀端
    • fd[1]:pipe的寫端

管道通訊是單向的阻塞性IO

藉助管道使兩個子進程相互通信

  • 一個子進程調用execvp函數,將執行結果寫入管道
  • 另一個子進程也是調用execvp函數,從管道中讀取命令結果進行過濾。
  • 涉及改變標準輸入輸出,重定向。

$ cat /etc/passwd |grep root數組

 

 
 1 #include <unistd.h>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 
 5 char *cmd1[3]={"/bin/cat","/etc/passwd",NULL};
 6 char *cmd2[3]={"/bin/grep","root",NULL};
 7 
 8 int main(void)
 9 {
10     int fd[2];
11     if(pipe(fd)<0)
12     {
13         perror("pipe error");
14         exit(1);
15     }
16     int i=1;
17     pid_t pid;
18     for(;i<=2;i++)
19     {
20         pid=fork();
21         if(pid<0)
22         {
23             perror("fork error");
24             exit(1);
25         }
26         else if(pid==0)
27         {
28             //child process
29             if(i==1)
30             {
31                 //子進程1,負責寫入數據
32                 close(fd[0]);//關閉讀端
33                 
34                 //將標準輸出重定向到管段的寫端
35                 if(dup2(fd[1],STDOUT_FILENO)
36                             !=STDOUT_FILENO)
37                 {
38                     perror("dup2 error");
39                 }
40                 close(fd[1]);
41 
42                 //調用exec函數執行cat命令
43                 if(execvp(cmd1[0],cmd1<0))
44                 {
45                     perror("excvp error");
46                     exit(1);
47                 }
48                 break;
49             }
50             if(i==2)
51             {
52                 //子進程2,負責從管道讀取數據
53                 close(fd[1]);//關閉寫端
54                 
55                 //將標準輸入重定向到管道的讀端
56                 if(dup2(fd[0],STDIN_FILENO)
57                                 !=STDIN_FILENO)
58                 {
59                     perror("dup2 error");
60                 }
61                 close(fd[0]);
62 
63                 //調用exec函數執行grep命令
64                 if(execvp(cmd2[0],cmd2)<0)
65                 {
66                     perror("execvp error");
67                     exit(1);
68                 }
69                 break;
70 
71             }
72         }else
73         {
74             //parent process
75             if(i==2)
76             {
77                 //父進程要等到子進程所有建立完畢纔去回收
78                 close(fd[0]);
79                 close(fd[1]);
80                 wait(0);
81                 wait(0);
82             }
83         }
84     }
85 }
相關文章
相關標籤/搜索