(匿名)管道

  (匿名)管道:一種進程間通訊形式。把從一個進程鏈接到另外一個進程的一個數據流成爲一個管道(固定大小內核緩衝區)。
管道的限制:一、半雙工(數據只能在一個方向流動)須要雙方通訊時,要創建兩個管道;
      二、只能用於共同祖先進程(具備親緣關係的進程)通訊,一般一個管道由一個進程建立,而後調用fork。spa

例如:ls | wc -w :   ls進程將輸出寫到管道,wc進程從管道獲取數據.code

  #include<unistd.h>
   int pipe(int fd[2]);  // 建立管道,返回兩個文件描述符,fd[0]表示讀端,fd[1]表示寫端.成功返回0,失敗返回-1blog

 具體狀態能夠以下圖:父進程建立管道後,調用fork,子進程的fd0 fd1 也指向了管道讀寫端進程

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/stat.h>
 4 #include<fcntl.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<string.h>
 9 
10 #include<signal.h>
11 #define ERR_EXIT(m)\
12     do\
13     {\
14         perror(m);\
15         exit(EXIT_FAILURE);\
16     }while(0)  //宏要求一條語句
17 int main(int argc,char*argv[])
18 {
19     int pipefd[2];
20     //建立管道
21     if(pipe(pipefd)==-1)
22         ERR_EXIT("pipe error");
23     pid_t pid;
24     if((pid=fork())==-1)
25         ERR_EXIT("fork error");
26     else if(pid==0){//子進程發送數據給父進程
27         close(pipefd[0]);
28         write(pipefd[1],"hello",5);
29         close(pipefd[1]);
30         exit(EXIT_SUCCESS);
31     }
32     close(pipefd[1]);
33     char buf[10];
34     read(pipefd[0],buf,10);
35     printf("buf=%s\n",buf);
36     close(pipefd[0]);
37     return 0;
38 }

 

  下面這個例子用pipe來模擬 ls | wc -w   :運行兩個進程 ls進程 、 wc -w進程。      用子進程運行ls,寫數據到管道。           父進程運行wc 從管道讀數據ip

正常狀況,ls輸出到標準輸出,於是須要先進行重定向(到管道寫端)。輸出到管道。  同理 wc也同樣string

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/stat.h>
 4 #include<fcntl.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<string.h>
 9 
10 #include<signal.h>
11 #define ERR_EXIT(m)\
12     do\
13     {\
14         perror(m);\
15         exit(EXIT_FAILURE);\
16     }while(0)  //宏要求一條語句
17 int main(int argc,char*argv[])
18 {
19     int pipefd[2];
20     if(pipe(pipefd)==-1)
21         ERR_EXIT("pipe error");
22     pid_t pid;
23     if((pid=fork())==-1)
24         ERR_EXIT("fork error");
25     else if(pid==0){
26         close(pipefd[0]);//關閉管道讀端
27         dup2(pipefd[1],STDOUT_FILENO);//1指向pipefd[1], 1指向管道寫端。  標準輸出,輸出到1;無論1指向哪,都記住輸出到 1  .等效於close(oldfd); fcntl(oldfd, F_DUPFD, newfd);
28         close(pipefd[1]);
29         execlp("ls","ls",(char*)0,NULL);//若果調用失敗將執行如下內容,ls 輸出到管道寫端
30         fprintf(stderr,"error ececutr ls\n");
31         exit(EXIT_SUCCESS);
32     }
33     close(pipefd[1]);//關閉管道寫端
34     dup2(pipefd[0],STDIN_FILENO);
35     close(pipefd[0]);//標準輸入是管道讀端
36     execlp("wc","wc","-w",(char*)0,NULL);//從標準輸入獲取
37     fprintf(stderr,"error ececutr ls\n");
38     return 0;
39 }

 

  補充一個例子來講明文件描述符拷貝。it

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/stat.h>
 4 #include<fcntl.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<string.h>
 9 
10 #include<signal.h>
11 #define ERR_EXIT(m)\
12     do\
13     {\
14         perror(m);\
15         exit(EXIT_FAILURE);\
16     }while(0)  //宏要求一條語句
17 int main(int argc,char*argv[])
18 {
19     close(0);//0和標準輸入斷開,0指向Makefile
20     open("Makefile",O_RDONLY);//Makefile做爲標準輸入
21     close(1);
22     open("Makefile2",O_WRONLY|O_CREAT|O_TRUNC,0644);//Makefile2做爲標準輸出
23     //拷貝makefile
24     execlp("cat","cat",(char*)0,NULL);//cat不帶參數,表示將標準輸入獲取數據寫入標準輸出
25     return 0;
26 }
相關文章
相關標籤/搜索