linux中pipe和dup2详解

1、什么是管道

  管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程); 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存中。数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

2、管道的创建

  int pipe(int fd[2])

  该函数创建的管道的两端处于一个中间进程,在实际应用中并没有太大意义,一般在pipe()创建管道后,再fork()一个子进程,然后通过管道实现父子进程之间的通信。

3、管道的读写规则

  管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。

4、pipe函数

  头文件:#include<unistd.h>

  函数原型: int pipe(int fd[2])

  函数参数:fd[2],管道的两个文件描述符,之后就是可以直接操作这两个文件描述符。其中fd[0]为读取端,fd[1]为写入端

  返回值:成功返回0,否则返回-1

  读fd[0]: close(fd[1]); read(fd[0], buf, BUF_SIZE);

  写fd[1]: close(fd[0]); read(fd[1], buf, strlen(buf));

5、例子

  

 1 #include <unistd.h>
 2 #include <stdio.h>
 3 
 4 int main()
 5 {
 6     int fd[2];
 7     char buf[1024];
 8     pid_t pid;
 9 
10     if(pipe(fd) != 0)
11     {
12         printf("pipe error\n");
13         return 0;
14     }
15 
16     pid = fork();
17 
18     if(pid == -1)
19     {
20         printf("fork error\n");
21         return 0;
22     }
23 
24     else if(pid > 0)
25     {
26         printf("This is the father process, here write a string to the pipe\n");
27         char s[] = "Hello! write a string in the father process\n";
28         close(fd[0]);
29         write(fd[1], s, sizeof(s));              // 向管道中写入数据
30 
31     }
32     else
33     {
34         printf("This is the child process, here read a string from the pipe\n");
35         close(fd[1]);
36         read(fd[0], buf, sizeof(buf));          //从管道中读取数据
37         printf("%s", buf);
38     }
39     waitpid(pid, NULL, 0);
40     return 0;
41 }
View Code

  输出结果为:

  This is the father process, here write a string to the pipe

  This is the child process, here read a string from the pipe

  Hello! write a string in the father process

  当管道中数据被读取后,管道为空。之后再read操作将默认的被阻塞,等待某些数据被写入。如需要设置为非阻塞,则可做如下设置:

  fcntl(filedes[0], F_SETFL, O_NONBLOCK);

  fcntl(filedes[1], F_SETFL, O_NONBLOCK);

6、dup2详解

  用来复制一个现存的文件描述符,使两个文件描述符指向同一个file结构体。

  其中头文件:#include <unistd.h>

  函数原型:int dup2(int oldhandle, int newhandle);

  例子还是使用上面那个例子,如下:

 1 #include <unistd.h>
 2 #include <stdio.h>
 3 
 4 int main()
 5 {
 6     int fd[2];
 7     char buf[1024];
 8     pid_t pid;
 9     int newfd;
10     if(pipe(fd) != 0)
11     {
12         printf("pipe error\n");
13         return 0;
14     }
15 
16     pid = fork();
17 
18     if(pid == -1)
19     {
20         printf("fork error\n");
21         return 0;
22     }
23 
24     else if(pid > 0)
25     {
26         printf("This is the father process, here write a string to the pipe\n");
27         char s[] = "Hello! write a string in the father process\n";
28         close(fd[0]);
29         write(fd[1], s, sizeof(s));              // 向管道中写入数据
30 
31     }
32     else
33     {
34         printf("This is the child process, here read a string from the pipe\n");
35         close(fd[1]);
36         dup2(fd[0], newfd);
37         read(newfd, buf, sizeof(buf));          //从管道中读取数据
38         printf("%s", buf);
39     }
40     waitpid(pid, NULL, 0);
41     return 0;
42 }
View Code

   运行的结果还是一样。只是在36行代码中调用了dup2,把fd[0]复制给newfd。



 

posted @ 2015-11-30 16:13  Hxinguan  阅读(5549)  评论(0编辑  收藏  举报