参考《操作系统导论》
介绍异步与多线程之前,先熟悉一下IO设备,这与异步关系密切
一、IO设备
1、问题:IO是如何集成进系统中的?一般的机制是什么?IO集成遇到的问题有哪些?如何解决集成遇到的问题?如何让它们变得高效?
为什么需要这样的布局?因为造价和物理布局,高性能的内存总线没有足够的空间来连接外围设备,而且高性能设备造价较高。
2、标准设备
由2部分组成,第1部分向系统展示的硬件接口,让系统软件来控制它的操作。第2部分内部结构主要包含一些复杂设备CPU、一些通用内存、设备相关的特性芯片。
3、标准协议具体
简化的设备接口包含3个寄存器:一个状态寄存器,可以查看设备的当前状态;一个命令寄存器,用于通知设备执行某个具体任务;一个数据寄存器,将数据传给设备或从设备接收数据。
操作系统与设备的经典交互,
while (status == BUSY)
;
write data to data register
write command to command regitster
while (status == BUSY)
;
这个简单的模型效率低下,轮询效率低下,在等待设备执行完成命令浪费大量CPU,如果此时切换到下一个就绪进程,就可以大大提高CPU使用率。
4、操作系统检查设备状态如何避免频繁轮询,降低CPU开销?
中断避免了频繁轮询,CPU向设备发送一个请求,然后切换到其他任务。当设备完成了自身操作,会抛出一个硬件中断,引发CPU跳转执行操作系统预先定义好的中断服务例程,或者更简单的中断处理程序。中断处理程序是一小段操作系统代码,它会结束之前的请求并且唤醒等待IO的进程继续执行。
中断并非总是最佳方案,高性能设备处理请求很块,通过在CPU第一次轮询时就可以返回结果。此时用中断反而会拖慢进程,因为切换到其他进程,处理中断,再切换回之前的进程代价不小的。
另外一种情况最好不要使用中断的场景是网络。网络端收到大量的数据包,如果每个包都发生一个中断,那么有可能引发操作系统发生活锁,即不处理中断无法处理用户层的请求。web服务器因为“点杠效应”而突然承受很重的负载。轮询可以更好的控制系统的行为,并允许web服务器先服务一些用户的请求。
另一种基于中断的优化就是合并。由于设备抛出中断之前往往会等待一小段时间,在此期间,其他请求可能很块完成,因此多次中断可以合并为一次中断抛出,从而降低处理中断的代价。等待太长会增加请求的延迟。
5、如何DMA进行更高效的数据传输?
前面介绍的还需要注意一点。具体的说,如果使用编程的IO将一大块数据传给设备,CPU又会因为参与将数据拷贝到设备,或者从设备上接收数据的过程中,导致CPU负载很重。浪费了时间和算力,本来可以服务其他进程的。
如何减少CPU的时间会浪费在向设备传输数据或从设备传出数据的过程中。从而提高CPU的使用率?
解决方案是使用DMA(Direct Memory Access)。DMA引擎是系统中的一个特殊设备,可以协调完成内存和设备间的数据传递,不需要CPU介入。
DMA工作过程如下,为了能够将数据传给设备,操作系统会通过编程告诉DMA引擎数据在内存的位置,要拷贝的大小以及要拷贝到哪个设备。在此之后操作系统就可以处理其他请求了。当DMA的任务完成后,DMA控制器会抛出一个中断来告诉操作系统自己已经完成数据传输。
中断与DMA的区别:
中断是CPU向设备发送一个请求,然后切换到其他任务。当设备完成了自身操作后,会抛出一个硬件中断,引发CPU跳转执行中断服务程序并重新唤醒等待IO的进程并继续执行。
DMA不需要CPU参与,操作系统会通过编程告诉DMA引擎数据在内存位置,要拷贝的大小以及要拷贝到哪个设备,在此操作系统就可以处理其他请求了。当DMA的任务完成后,DMA控制器会抛出一中断告诉操作系统自己已完成数据传输。