目录
前言
一、通信的本质
二、匿名管道
1.通信资源——文件缓冲区
2.为什么叫匿名管道?
编辑
3.匿名管道的创建过程
4.pipe函数
小结
5.一些问题
1)匿名管道为什么要求父子进程将原本的读/写权限只保留一个
2)为什么一开始父进程要以读/写打开文件
三、命名管道
1.mkfifo函数
2.创建命名管道文件而不用普通文件的原因
3.有关管道的一些细节
1)管道为什么叫管道
2)在通信过程中,创建的管道文件大小不变的原因
3)管道两端读写速度不匹配的情况
4)管道的特征
总结
前言
首先,什么是通信呢?
①进程间的数据传输;②进程间的信息通知;③一个进程控制另一个进程(如gdb调试)。
为什么要有进程间的通信?
在实际应用中常需要多进程协调,如
cat file | grep 'name'
怎么实现通信?
可以通过管道实现进程间的通信。
一、通信的本质
由于进程具有独立性,故想要使独立的进程能够通信需要满足以下条件:
1.OS需要直接或者间接给通信双方的进程提供额外的“内存空间”;
2.需要让通信双方进程都能同时看到这份OS提供的额外“资源”。
由于OS提供的这份资源的不同,可以划分为不同的通信方式
二、匿名管道
怎么样才能使得两个进程能同时看到系统提供的资源呢?
匿名管道通过利用“子进程会继承父进程的部分属性信息”的特性,以实现父子进程间的通信。
1.通信资源——文件缓冲区
当父进程打开某个“文件”后,在创建一个子进程,该子进程一定继承了位于父进程PCB(task_strutc)中的文件描述符表struct file* fd_array[ ],那么此时父子进程便可以访问同一份文件。
每个文件在被打开后,操作系统为方便管理这些被打开的文件会为其创建file结构体对象,而file中都有着缓冲区。
于是父子进程能够同时访问的这个文件的缓冲区就能够成为进程通信的一种资源。
2.为什么叫匿名管道?
换句话说,并非真的需要父子进程同时打开磁盘中的某一个文件,只需OS在内存中创建一个file专门用于通讯即可。所以管道文件不会进行磁盘刷新。
(实际上file结构体中有个联合体成员,专门用于表示该file指向的文件是普通文件还是管道文件)
3.匿名管道的创建过程
1)父进程通过pipe函数创建管道
父进程通过pipe函数,分别用读和写的方式打开同一个文件。
2)父进程fork创建出子进程
由于子进程会继承父进程的一部分内容属性,故此时这个管道文件同时被两个进程分别以读和写的方式指向。
3)根据实际需要,父进程关闭读端,子进程关闭写端,或者父进程关闭写端,子进程关闭读端。
这样这个管道文件便就变成了,一端进程在往里写数据,另一个进程在另一端读数据。
4.pipe函数
作用:创建一个内存级文件,用于管道通信。
参数:该参数为输出型参数,OS将创建好的文件以读写方式打开,并通过传入的数组参数返回读写两个操作的文件描述符。返回的数组,其中0下标元素存储的是读文件描述符,1下标的是写文件描述符。
返回值:成功返回0,失败返回-1.
小结
父进程通过pipe系统调用以读写方式打开一个内存级文件。然后通过创建子进程并使得子进程继承对该进程的读写方式后,再根据实际需要关闭父子进程的读或写端,进而形成一条单向的通信信道。这条信道是基于文件的,故被称为管道文件。
5.一些问题
1)匿名管道为什么要求父子进程将原本的读/写权限只保留一个
2)为什么一开始父进程要以读/写打开文件
三、命名管道
上面的匿名管道有个使用前提是:通信双方需是具有“血缘”关系的进程,如父子进程。那没有“血缘”关系的两个进程应该如何通信呢?
同理,只要我们让两个欲通信的进程双方看到同一份资源,即可实现“无血缘关系”的进程间通信
1.mkfifo函数
作用:mkfifo函数可以在指定的路径创建一个命名管道文件。
参数:第一个参数是希望创建的命名管道文件所在路径,第二个参数是初始化命名管道文件权限。
返回值:成功返回0,失败返回-1.
命名管道是如何做到让不同的进程,看到同一份资源的?
路径 + 文件名 = 唯一性,可以让不同的进程打开指定名称(路径+文件名)的同一份文件。
2.创建命名管道文件而不用普通文件的原因
3.有关管道的一些细节
①管道一般都是单项的,用于数据的单项通信;
②管道必须要有入口和出口——读端和写端;
1)管道为什么叫管道
2)在通信过程中,创建的管道文件大小不变的原因
无论是匿名管道还是命名管道,其本质是一个内存级的缓冲区,没有向外设如磁盘中IO,故管道文件的大小没有发生变化。
3)管道两端读写速度不匹配的情况
①读慢写快:由于管道文件所能容纳的数据也是有上限的(默认大小通常为64KB,具体大小可能因系统而异),故管道会被写端写入的数据填满,此时OS会阻塞写端进程,等待读端读取数据,直到管道中有着剩余空间。
②读快写慢:读端在读,但管道中没有数据,此时OS也会将正在读取的进程阻塞,等待写端写入数据。
③特殊情况:
a.当写端进程关闭后,读端会读到0;
b.当读端进程关闭,OS会给写端进程发送信息,终止写端。
4)管道的特征
1)管道的生命周期由读写进程决定,若两个进程都关闭了读写,则管道的生命也就结束了。
2)匿名管道可以在具有“血缘关系”的进程间进行通信,常用于父子进程通信。
3)管道是面向字节流的,即管道不在乎两个进程通信的是数字还是字符串,管道中流动的永远是字节。
4)管道是半双工的——单向通信。
5)管道读和写操作可以同时进行(并发)。写/读操作不需要等待读/写操作完成(只要缓冲区未满)。管道通过内核缓冲区实现读写并发,只要缓冲区既不满也不空,读写操作就能同时进行
总结
本文讨论了管道通信的原理和相关函数的用法。
本文先从进程通信的本质“让通信双方看到同一份资源”入手,再通过匿名管道的原理和创建过程深入理解管道通信的原理,最后介绍了命名管道以及有关管道的一些细节。