IO多路复用

本文深入探讨Linux中的用户空间和内核空间,解析PIO与DMA的I/O方式,比较缓存IO与直接IO的优劣。重点讨论了同步IO、异步IO、阻塞IO和非阻塞IO的概念及其区别。此外,详细介绍了Reactor和Proactor两种IO设计模式,分析其特点、应用场景及优缺点,帮助理解高性能IO模型。
摘要由CSDN通过智能技术生成

理解Linux中的用户空间和内核空间

我们这里是讲Linux系统!
学习 Linux 时,经常可以看到两个词:User space(用户空间)和 Kernel space(内核空间)!
User space(用户空间):用户程序的运行空间
Kernel space(内核空间):Linux系统运行的空间
在这里插入图片描述
Kernel space可以执行任何命令,调用系统的一切资源;User space只能执行简单的元算,不能直接调用系统的资源,必须通过系统接口(system call)才能向内核发出指令。
通过系统接口,进程可以从用户空间切换到内核空间!如下面伪代码:

String str="my string";//用户空间
x=x+2;//用户空间
file.write(str)//切换到内核空间
y=x+4;//用户空间

PIO与DMA

慢速I/O设备和内存之间的数据传输方式。

  1. PIO:我们以磁盘来说,早期磁盘和内存之间的数据传输需要CPU控制,也就是说如果我么要读磁盘文件的数据到内存中,数据要经过CPU转储转发,这种方式称为PIO。这种设计非常不合理,需要占用大量的CPU时间来读取文件,如果文件很大,很容易造成系统几乎停止响应。
  2. DMA:由于PIO的缺点,后来即用DMA替代了PIO。DMA可以不经过CPU而直接进行磁盘和内存的数据交互。在DMA方式下,CPU只需要向DMA控制器发送指令,让DMA控制器来处理数据的传送即可,DMA通过系统总线来传输数据,传送完再通知CPU,这样就很大程度降低了CPU的占用率,大大节省了系统资源。DMA的传输速度与PIO的速度其实相差不大,因为快慢取决于慢速设备的速度!
    在现在的计算机中PIO方式的很少见了!

缓存IO和直接IO

  1. 缓存IO:数据从磁盘通过DMA方式copy到内核空间,再从内核空间通过cpu copy到用户空间
  2. 直接IO:数据直接从磁盘通过DMA方式copy到用户空间

缓存IO又被成为标准I/O,大多数文件系统的默认I/O操作都是缓存I/O。特点是:

读操作:操作系统检查内核中的缓冲区是否有需要的数据,如果已经缓存了,那么就直接从缓存中返回;否则从磁盘中读取到内存缓存中,再返回给用户内核。
写:将数据从用户空间复制到内核内存缓寸中。这是对用户程序来讲写操作已经完成了,至于什么时候再写到磁盘中有操作系统决定,除非显示的调用sync同步命令。
缓存I/O的优点:
	1)在一定程度上分离了内核空间和用户空间,包含系统本身的运行安全
	2)可以减少磁盘的读的次数,从而提高性能
缓存I/O的缺点:
	1)在缓存I/O机制中,DMA方式可以将数据直接从磁盘读到也内存缓存中,或者将数据从内存缓存中写回到磁盘中,而不能直接在用户空间和磁盘之间进行数据传输,这样就会导致用户空间和内核空间之间进行多次数据拷贝操作,这些数据拷贝操作所带来的CPU已经内存开销是非常大的。

直接IO

就是应用程序(用户内核)直接访问磁盘数据,而不经过内核缓存区。也就是绕过了内核缓存区,自己管理I/O缓存区,这样减少了从内核缓存区到用户程序的数据复制。
引入内核缓冲区的目的在于提高磁盘文件的访问性能,因为当进程需要读取磁盘文件时,如果文件内容已经在内核缓
冲区中,那么就不需要再次访问磁盘;而当进程需要向文件中写入数据时,实际上只是写到了内核缓冲区便告诉进程
已经写成功,而真正写入磁盘是通过一定的策略进行延迟的。
直接IO的缺点是如果访问的数据不再应用程序缓存中,那么每次数据都会直接从磁盘中加载读取,这个过程会非常慢。通常直接I/O和异步I/O结合使用会得到较好的性能

IO访问方式(不多介绍)

  1. 磁盘IO
  2. 网络IO

同步IO和异步IO

同步IO和异步IO是针对应用程序和内核的交互而言的,同步指的用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。

指的是用户空间和内核空间数据的交互方式
同步:用户空间要数据,必须等待内核空间给他才能做其他事情
异步:用户空间要数据,不需要等待内核空间给他,才做其他事情。内核空间会异步通知用户进程,并把数据直接给用户空间

阻塞IO和非阻塞IO

阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

指的是用户就和内核空间IO操作的方式
堵塞:用户空间通过系统调用(systemcall)和内核空间发送IO操作时,该调用是堵塞的
非堵塞:用户空间通过系统调用(systemcall)和内核空间发送IO操作时,该调用是不堵塞的,直接返回的,只是返回时,可能没有数据而已
同步IO和异步IO是对交互数据的整个过程而言,而阻塞IO和非阻塞IO针对的是整个过程中的其中的一个调用(systemcall)操作而已

IO设计模式之Reactor和Proactor

平时接触的开源产品如Redis、ACE,事件模型都使用的Reactor模式;而同样做事件处理的Proactor,由于操作系 统的原因,相关的开源产品也少;这里学习下其模型结构,重点对比下两者的异同点;

反应器Reactor

反应器设计模式(Reactor pattern)是一种为处理并发服务请求,并将请求提交到 一个或者多个服务处理程序的事件设计模式。当客户端请求抵达后,服务处理程序 使用多路分配策略,由一个非阻塞的线程来接收所有的请求,然后派发这些请求至 相关的工作线程进行处理。

Reactor模式主要包含下面几部分内容
  1. 初始事件分发器:用于管理Event Handler,定义注册、移除Event Handler等操作。它还作为Reactor模式的入口调用Synchronous Event Demultiplexer的select方法以阻塞等待事件返回,当阻塞等待返回时,根据事件发生的Handle将其分发给对应的Event Handler处理,即回调 EventHandler中的handle_event()方法
  2. 同步(多路)事件分离器:无限循环等待新事件的到来,一旦发现有新的事件到来,就会通知初始事件分发器去调取特定的事件处理器。
  3. 系统处理程序:操作系统中的句柄,是对资源在操作系统层面上的一种抽象,它可以是打开的文件、一个连接(Socket)、Timer等。由于Reactor模式一般使用在网络编程中,因而这里一般指Socket Handle,即一个网络连接(Connection,在Java NIO中的Channel)。这个Channel注册到Synchronous Event Demultiplexer中,以监听Handle中发生的事件,对ServerSocketChannnel可以是CONNECT事件,对 SocketChannel可以是READ、WRITE、CLOSE事件等。
  4. 事件处理器:定义事件处理方法,以供Initialization Dispatcher回调使用

对于Reactor模式,可以将其看做由两部分组成,一部分是由Boss组成,另一部分是由worker组成。Boss就像老板 一样,主要是拉活儿、谈项目,一旦Boss接到活儿了,就下发给下面的work去处理。也可以看做是项目经理和程序 员之间的关系。

为什么使用Reactor

并发系统常使用reactor模式代替常用的多线程的处理方式,节省系统的资源,提高 系统的吞吐量。 例如:在高并发的情况下,既可以使用多处理处理方式,也可以使用Reactor处理方式。

多线程的处理:

为每个单独到来的请求,专门启动一条线程,这样的话造成系统的开销很大,并且在单核的机上,多线程并不能提高系 统的性能,除非在有一些阻塞的情况发生。否则线程切换的开销会使处理的速度变慢。

Reactor模式的处理:

服务器端启动一条单线程,用于轮询IO操作是否就绪,当有就绪的才进行相应的读写操作,这样的话就减少了服务器产 生大量的线程,也不会出现线程之间的切换产生的性能消耗。(目前JAVA的NIO就采用的此种模式,这里引申出一个问 题:在多核情况下NIO的扩展问题)

以上两种处理方式都是基于同步的,多线程的处理是我们传统模式下对高并发的处 理方式,Reactor模式的处理是现今面对高并发和高性能一种主流的处理方式。

Proactor模式

运用于异步I/O操作,Proactor模式中,应用程序不需要进行实际的读写过程,它只需要从缓存区读取或者写入即 可,操作系统会读取缓存区或者写入缓存区到真正的IO设备.

Proactor主动器模式包含如下角色

  1. Handle 句柄;用来标识socket连接或是打开文件;
  2. Asynchronous Operation Processor:异步操作处理器;负责执行异步操作,一般由操作系统内核实现;
  3. Asynchronous Operation:异步操作
  4. Completion Event Queue:完成事件队列;异步操作完成的结果放到队列中等待后续使用
  5. Proactor:主动器;为应用程序进程提供事件循环;从完成事件队列中取出异步操作的结果,分发调用相应的 后续处理逻辑;
  6. Completion Handler:完成事件接口;一般是由回调函数组成的接口;
  7. Concrete Completion Handler:完成事件处理逻辑;实现接口定义特定的应用处理逻辑;
对比两者的区别
主动和被动
以主动写为例:
		>1) Reactor将handle放到select(),等待可写就绪,然后调用write()写入数据;写完处理后续逻辑;
		>2) Proactor调用aoi_write后立刻返回,由内核负责写操作,写完后调用相应的回调函数处理后续逻辑;

可以看出,Reactor被动的等待指示事件的到来并做出反应;它有一个等待的过程,做什么都要先放入到监听事件集 合中等待handler可用时再进行操作; Proactor直接调用异步读写操作,调用完后立刻返回;

实现

Reactor实现了一个被动的事件分离和分发模型,服务等待请求事件的到来,再通过不受间断的同步处理事件,从而做出反应;
Proactor实现了一个主动的事件分离和分发模型;这种设计允许多个任务并发的执行,从而提高吞吐量;并可执行耗时长的任务(各个任务间互不影响)

优点

Reactor实现相对简单,对于耗时短的处理场景处理高效; 操作系统可以在多个事件源上等待,并且避免了多线程 编程相关的性能开销和编程复杂性; 事件的串行化对应用是透明的,可以顺序的同步执行而不需要加锁; 事务分 离:将与应用无关的多路分解和分配机制和与应用相关的回调函数分离开来,
Proactor性能更高,能够处理耗时长的并发场景;

缺点

Reactor处理耗时长的操作会造成事件分发的阻塞,影响到后续事件的处理;
Proactor实现逻辑复杂;依赖操作系统对异步的支持,目前实现了纯异步操作的操作系统少,实现优秀的如 windows IOCP,但由于其windows系统用于服务器的局限性,目前应用范围较小;而Unix/Linux系统对纯异步的支 持有限,应用事件驱动的主流还是通过select/epoll来实现;

适用场景

Reactor:同时接收多个服务请求,并且依次同步的处理它们的事件驱动程序;
Proactor:异步接收和同时处理多 个服务请求的事件驱动程序;

浅谈五种IO模型

高性能IO模型浅析:
服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:

  1. 同步阻塞IO(Blocking IO):即传统的IO模型。
  2. 同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为 NONBLOCK。注意这里所说的NIO并非Java的NIO(New IO)库。
  3. IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的 Selector和Linux中的epoll都是这种模型。
  4. 异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。
IO模型举例理解
  1. 阻塞IO, 给女神发一条短信, 说我来找你了, 然后就默默的一直等着女神下楼, 这个期间除了等待你不 会做其他事情, 属于备胎做法.
  2. 非阻塞IO,给女神发短信, 如果不回, 接着再发, 一直发到女神下楼, 这个期间你除了发短信等待不会 做其他事情, 属于专一做法.
  3. IO多路复用, 是找一个宿管大妈来帮你监视下楼的女生, 这个期间你可以些其他的事情. 例如可以顺便 看看其他妹子,玩玩王者荣耀, 上个厕所等等. IO复用又包括 select, poll, epoll 模式. 那么它们 的区别是什么? 3.1 每一个女生下楼, select大妈都不知道这个是不是你的女神, 她需要 一个一个询问, 并且select大妈能力还有限, 最多一次帮你监视1024个妹子 3.2 不限制盯着 女生的数量, 只要是经过宿舍楼门口的女生, 都会帮你去问是不是你女神 3.3 不限制盯着女 生的数量, 并且也不需要一个一个去问. 那么如何做呢? epoll大妈会为每个进宿舍楼的女生脸上贴上一 个大字条,上面写上女生自己的名字, 只要女生下楼了, epoll大妈就知道这个是不是你女神了, 然后大 妈再通知你.

上面这些同步IO有一个共同点就是, 当女神走出宿舍门口的时候, 你已经站在宿舍门口等着女神的, 此时你属于同步等待状态

接下来是 的情况 你告诉女神我来了, 然后你就去王者荣耀了, 一直到女神下楼了, 发现找不见你了, 女神再给你打电话通知你, 说我下楼了, 你在哪呢? 这时候你才来到宿舍门口. 此时属于逆袭做法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值