操作系统-进程通信
进程通信是指进程间的信息交互。根据通信双方通信的实现方式可以分为四大类:共享存储器通信、管道通信、消息传递通信、C/S通信
共享存储器通信
相互通信的进程共享数据结构或存储区,进程间通过这些空间进行通信。
共享数据结构的通信
同一主机种不同进程间的通信方式(如生产者-消费者问题)。操作系统仅提供用于存储共享数据结构的存储空间,对共享数据结构的创建与同步处理,则是由程序员自己负责的,这种方式仅适合少量同构数据的传递。
共享存储区的通信
为了传输大量、异构数据,可以划分出一块所有进程都可访问的共享存储区域,通过该区域进行进程间的数据交换
管道通信
所谓管道,即Channel,就是用于连接一个读进程和一个写进程,实现两个进程间通信的共享文件,又称pipe文件。
管道通信机制提供了三方面协调能力:
- 互斥:当一个进程正在对pipe执行读/写操作时,另一个进程必须等待
- 同步:进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞
- 双方:只有确定了通信的对方存在时才能进行通信
消息传递通信
进程无需借助任何共享数据结构或共享存储区域,而是以格式化的消息为单位,将通信的数据封装在消息中,并利用操作系统提供的一组通信命令(原语)在进程中进行消息传递
这种通信机制在生产中使用很广:
- 异构系统中一般使用JSON格式的消息通信
- 同构系统中一般会使用更加符合自身业务需求的消息格式进行通信。
C/S通信
C/S通信机制更适合网络环境下进程间的通信。实现方式有两种:
Socket通信
Socket,即套接字通信,一个套接字就是一个通信标识类型的数据结构,包含了通信目的地址、端口号、通信协议等,当然还包括真正要进行网络传输的数据,网络通信技术BIO、NIO、AIO的底层用的都是Socket通信
RPC通信
RPC(Remote Procedure Call),远程过程调用,是一种通信协议,或者说是一种通信模型,RPC通信会使一台主机上的进程调用另一台主机上的进程,使用起来就像调用本地进程一样,无需额外操作。
一致性通信模型
为了实现数据一致性目的而构建的一种通信模型。
拜占庭将军问题(数据一致性)
拜占庭的司令在发动军事行为前,需要听取各个领地将军的意见。而各个领地的将军会让通信兵把意见带给司令。但是因为司令无法判断通信兵是否为间谍,进而无法判断各将军的意见是否属实。所以通常认为通信兵带来的消息是不能轻易相信的。
该问题要说明的意思是,在不可靠信道(通信兵)上试图通过消息传递的方式达到一致性是不可能。
两种通信模型
一般情况下,分布式系统为实现节点中数据的一致性,各节点间通常采用两种一致性通信模型:星型通信模型与网状通信模型,无论哪种模型,其实现一致性的前提是:不存在拜占庭将军问题,即通信是安全可靠的,集群节点间传递的消息是不会被篡改的。paxos算法采用的网状通信模型。
星型模型存在中心化问题:中心(拜占庭)一旦出问题,整个通信模型就会崩溃。
网状模型实现较为复杂,但是可靠性较好。
Reactor通信模型
在高性能的网络通信设计中,有两个比较著名的网络通信模型Reactor和Proactor模型,其中Reactor模型属于同步非阻塞I/O的网络通信模型,而Proactor属于一部非阻塞I/O的网络通信模型。
Reactor单线程模型
Reactor单线程模型,指的是当前的主机会为每一个通信对端形成一个Channel,而所有这些channel都会与一个线程相绑定,该线程用于完成它们间的所有通信处理。
selector会根据每个Channel的就绪状态分配线程资源。
就绪事件分为4类:
- 连接就绪
- 接受连接就绪
- 读就绪
- 写就绪
在高并发情况下,容易出现性能问题。
Reactor线程池模型
Reactor单线程模型中使用一个线程处理所有通信对端的所有请求,在高并发场景中会严重影响系统性能。所以,就将单线程模型中的一个线程替换为线程池,大大提高了性能。
Reactor多线程池模型
在高并发的情况下,为处理比较耗时的IO请求,服务器将连接请求和IO请求分开,形成Reactor多线程池模型。
当客户端通过处理连接请求的Channel连接上服务器后,系统会为该客户端再生成一个子Channel专门用于处理该客户端的IO请求。这两类不同的Channel连接着两类不同的线程池,而线程池中的线程数量中的线程数量可以根据需求分别配置,提高了系统性能。
Proactor通信模型
由于Reactor属于同步非阻塞I/O的网络通信模型,其同步性导致其处理高耗时的IO时性能会下降。于是就产生了异步非阻塞I/O的网络通信模型Proactor。
图片来源于网络