linux进程间通信--无名管道

管道

只能用于具有亲缘关系的进程之间通信是一个半双工的通信模式,

具有固定的写读端和写端,管道可以看成一种特殊的文件,对它可以使用普通的read、write等操作

管道的创建:

#include <unistd.h>

int pipe(int fd[2])

该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,

然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。

管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。

即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。

如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。

从管道中读取数据: 如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;

当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,

如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);

或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。

注:(PIPE_BUF在include/linux/limits.h中定义,不同的内核版本可能会有所不同。Posix.1要求PIPE_BUF至少为512字节,有的是4096)。

向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。

如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。 注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,默认动作则是应用程序终止.

列子:

无名管道

1 #include<unistd.h>
2 #include<sys/types.h>
3 #include<errno.h>
4 #include<stdio.h>
5 #include<stdlib.h>
6
7 int main()
8 {
9       int pipe_fd[2];
10       pid_t pid;
11       char buf_r[100];
12       char* p_wbuf = NULL ;
13       int r_num = 0 ;
14     memset(buf_r , 0 ,sizeof(buf_r));
15       if(pipe(pipe_fd) < 0) //返回0表示创建失败
16        {
17            printf("pipe create error ");
18            return -1;
19        }
20        if( (pid=fork()) == 0) //子进程中 fork()创建子进程会继承父进程的所有,包括管道啦。
21        {
22            printf(" ");
23            close(pipe_fd[1]);//关闭写管道
24            sleep(1);
25            if((r_num = read(pipe_fd[0],buf_r,100)) >0) // 返回读写数
26              {
27                printf("%d numbers read from the pipe is %s ",r_num ,buf_r);

                    close(pipe_fd[0]);
29                exit(0);
30              }
31        }
32        else if(pid > 0) //父进程中
33        {
34          close(pipe_fd[0]);
35          if(write(pipe_fd[1], "Hello " , 5) != -1)
36          printf("parent write1 success! ");
37          if(write(pipe_fd[1]," Pipe" , 5) != -1)
38          printf("parent write2 success! ");
39          close(pipe_fd[1]);
40           sleep(1);
41           waitpid(pid ,NULL ,0); //等子进程结束
42           exit(0);
43        }
44      return 0;
45 }

原文地址:https://www.cnblogs.com/yuankaituo/p/4246545.html