管道(Pipe)

管道是Unix的传统IPC机制之一,特点是:

1、仅用于有亲缘关系的进程之间;

2、单向数据流,即打开一个管道,一端仅用于读,另一端仅用于写;

3、传递的是字节流;

4、对它的read总是从头部返回数据,对它的write总是从尾部添加数据;

5、对于空管道:

  a. 写端打开,阻塞read将一直阻塞到管道有数据(可以是EOF);非阻塞read返回EAGAIN;

  b. 写端未打开,read返回0;

  c. 读端未打开,write操作产生SIGPIPE。

例子:

1、父子进程间通信。(子进程传递一个文件名给父进程,由父进程打开文件并将数据传给子进程)

pipe
 1 #include "unpipc.h"
 2 void do_client(int, int);
 3 void do_server(int, int);
 4 
 5 // pipe is one-way channel.
 6 int main()
 7 {
 8     int fd1[2], fd2[2];
 9     // creating pipes
10     if (pipe(fd1) || pipe (fd2))
11         SYS_ERR();
12     pid_t pid;
13     if ((pid = fork()) < 0)
14         SYS_ERR();
15     if (pid == 0) {    //child
16         close(fd1[0]);
17         close(fd2[1]);
18         do_client(fd1[1], fd2[0]);
19         exit(EXIT_SUCCESS);
20     } else {
21         close(fd1[1]);
22         close(fd2[0]);
23         do_server(fd2[1], fd1[0]);
24         close(fd2[1]); // this will let the read-end get a EOF
25         /*close(fd1[0]);*/    // no-necessary
26         if (waitpid(pid, NULL,1) < 0)
27             SYS_ERR();
28         exit(EXIT_SUCCESS);
29     }
30 }
31 // fd0 for read, fd1 for write
32 void do_client(int fd1, int fd0)
33 {
34     char buf[MAX_BUF+1] = {0};
35     // read filename
36     if (fgets(buf, MAX_BUF, stdin) == NULL)
37         return;
38     int len = strlen(buf);
39     if (buf[len-1] == '\n')    // delete newline
40         len--;
41     if (write(fd1, buf, len) < 0)
42         SYS_ERR();
43     while ((len = read(fd0, buf, MAX_BUF)) > 0)
44         buf[len] = 0, fputs(buf, stdout); // use comma
45     if (len < 0)
46         SYS_ERR();
47     return;
48 }
49 
50 void do_server(int fd1, int fd0)
51 {
52     char buf[MAX_BUF+1] = {0};
53     int n;
54     if ((n = read(fd0, buf, MAX_BUF)) < 0)
55         SYS_ERR();
56     if (n == 0)
57         return ;    // recv EOF
58     buf[n] = 0;    // add null terminator
59     int fd = open(buf, O_RDONLY, 0);
60     if (fd < 0) {
61         snprintf(buf, MAX_BUF, "%s\n", strerror(errno));
62         if (write(fd1, buf, strlen(buf)) < 0)
63             SYS_ERR();
64     } else {
65         while ((n = read(fd, buf, MAX_BUF)) > 0) {
66             buf[n] = 0;
67             if (write(fd1, buf, n) < 0)
68                 SYS_ERR();
69         }
70         if (n < 0)
71             SYS_ERR();
72         close(fd);
73     }
74     return ;
75 }

2、shell命令行的管道,如“ls | sort”,它将前一个命令的输出作为后一个命令的输入。

popen
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <errno.h>
 4 
 5 int main(int argc, char **argv)
 6 {
 7     if(2 != argc) {
 8     fputs("usage< ./popen proc >\n", stderr);
 9     return -1;
10     }
11     FILE *fp = popen(argv[1], "w");
12     if (NULL == fp) {
13         fprintf(stdout, "%s\n", strerror(errno));
14     return -1;
15     }
16         
17     fputs("Hello, world.", fp);
18     fputs("This is China!\n", fp);
19     pclose(fp);
20     return 0;
21 }
pout

posted on 2013-04-22 20:10  逆转的旋律  阅读(447)  评论(0)    收藏  举报

导航