目录
1.进程间通信介绍
1.1.简要介绍
进程间通信(Inter-Process Communication,简称IPC)是指在不同进程之间传播或交换信息
我们知道:进程之间是独立的,所以进程之间的进程间通信一定不是两个进程直接通信的,为了保证进程间的独立性和实现进程间通信,操作系统就设计了若干种进程间通信方式,来实现多进程之间的协同工作。
1.2.进程间通信的目的
- 数据传输:一个进程需要将它的数据发送给另一个进程
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变。
1.3.进程间通信的本质
进程间通信就是不同的进程通过 操作系统 这一个中间媒介,结合设计好的通信方式来进行通信的,本质上就是实现不同的进程能够访问到同一份资源,并从资源上获取信息。
- 比如存在进程A、B,其中A进程写入数据进入缓冲区,而B进程从这一块缓冲区中读取内容,这时A、B并没有之间接触,而是从中间商“缓冲区”处使得B进程获取信息。
- 同理,A、B进程可以从某一块缓冲区中读取数据。
2.管道
管道是一种基于文件系统的进程间通信方式,管道文件允许访问它的进程,通过它来对一块缓冲区的数据进行访问,通过进程对这一块缓冲区进行读写,来实现进程间数据的交换。
2.1.管道的通信原理
生活中,我们见到的管道,当有流形成时,这个管道在某一个时刻或者时间段都是只允许单向流通的,比如水管中水的流动一般都是单向的,我们也没有见过管道发挥功能时,先向左流再从右往左流吧……
进程间的管道通信也是如此,一般来说:管道这种通信方式是单向流动的
因为进程具有独立性,所以进程是不能够直接进行通信的,比如A,B进行通信,只允许进行A--中间渠道--B或者B--中间渠道--A ,所以管道的通信原理就是作为中间渠道,在操作系统中,系统实现管道的功能是通过加载进内存的文件缓冲区实现的,并没有实际对管道文件进行操作,而是通过A/B往缓冲区读/写内容,然后B/A进行读/写……
另外管道的通信具有以下4种情形(规定)和三种特性:
四种情形:
- 正常情况下,如果管道中没有数据,也就是写端当前没有写入时,读端必须等待,直到写端提供数据。(这里体现了管道通信具有同步性,稍微埋个伏笔)
- 如果管道中的数据写满时,如果需要继续写入,写端必须等待,直到读端读取完数据,写端才可以继续写入。
- 写端关闭时,读端直接接收到read()函数的返回值为0,表示读取结束,读到文件结尾。
- 读端关闭时,写端不会直接关闭,如果写端仍不断写入,操作系统会介入杀掉写端进程。
三种特性:
- 管道是单向通信的,是一种半双工通信
- 管道是面向字节流的,也就是对应C++IO流中的字符流,管道可以是整型流、字符流
- 管道的生命周期是伴随进程的,因为管道通信的本质就是通过文件系统在内存中开辟一块缓冲区,来间接实现进程间通信的
基于4种情形和三种特性,操作系统实现了两种管道通信方式:匿名管道和命名管道,前者只能用于具有血缘关系的进程,后者能用于所有进程……
2.2.匿名管道
C语言提供创建匿名管道的函数方法:
接下来我们通过匿名管道的测试来探究一下其原理:
// 匿名管道的测试
void test1()
{
// 设置管道的文件描述符数组
int pipefd[2] = {0};
// 将fd传入pipe接收返回值
int n = pipe(pipefd);
// 返回值为3,4表示占用了文件指针数组第3个、第4个文件
cout << pipefd[0] <<" "<< pipefd[1] << endl;
int pipefd1[2] = {0};
int m = pipe(pipefd1);
cout << pipefd1[0] << " " << pipefd1[1] << endl;
}
通过这段代码的测试,我们发现除了0(stdin),1(stdout),2(stderr),我们在创造一个匿名管道时,会占用两个文件fdÿ