管道
每个进程都拥有自己的独立的虚拟地址空间和页表结构, 所以每个进程是独立的, 进程间必须借助媒介来进行通信, 这些媒介包括管道, 共享内存 消息队列 和信号量
把从一个进程连接到另一个进程的一个数据流称为一个“管道” ; 通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道 ; 进程退出,管道释放,所以管道的生命周期随进程; ,内核会对管道操作进行同步与互斥
管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
1. 匿名管道
匿名管道(在内核中创建的这块缓冲区并没有一个标识), 但是内核会返回给我们用户两个文件描述符(fd[0]缓冲区的读端, fd[1]缓冲区的写端),
创建匿名管道的接口 int pipe(int fd[2])
fd[2] : 文件描述符数组,其中fd[0]表示读端, fd[1]表示写端;
接口返回值有两 返回0 表示创建成功; 返回-1(也就是小于0)表示失败
由于这段缓冲区没有标识, 而对于没有关系的两个进程 想要通过这个缓冲区来进行数据交换时, 不同的进程是找不到这片缓冲区的,
无法去修改缓冲区中的内容, 所以也就无法进行数据交换, -------> 所以匿名管道只适合具有亲缘关系的进程之间,
父进程先去创建一个管道, 然后在父进程的文件描述表files_struct中就有fd[0]和fd[1], 分别对应3号和4号文件描述符,
然后再创建出来子进程, 由于子进程会拷贝父进程的PCB, 所以文件描述表也被拷了, 所以在子进程中也有了fd[0], fd[1],也对应他的3,4文件描述符, 这时候父子进程就可以通过操作文件描述符来操作缓冲区,
同时匿名管道又是一个半双工的, 数据流向只能是从写端流到读端(like水管), 数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
加上每次将字节写入到缓冲区后, 数据之间时没有明确的数据边界的, 所以在读端读的时候, 他可以按自己的需求读任意个数的字节,也就是任意大小的数据, 且管道大小(PIPE_SIZE