下面我们来讨论I/O数据传输
在I/O子系统当中
设备和CPU之间的数据传输性能
也是我们这里关注的一个重要的问题
CPU和设备之间的数据传输
有这样两种方式
第一种是程序控制I/O
也就是说CPU通过in/out指令
或者说load/ store指令
如果说后一种情况
你是做了内存映射的话
那它是通过load和store指令
来完成设备和CPU之间的数据交换
那这种方式由于需要CPU的参与
它的硬件实现相对简单
编程也是比较容易的
它的问题主要是在于消耗的CPU时间
和你要传输的数据量是成正比的
数据量越大
它的传输时间开销也就越大
这时候它适用于简单的小型的设备I/O
如果说你传送数据量大的话
这种方式对CPU的占用就是比较多的
第二种方式是DMA直接存储访问
它是让设备控制器
直接可以访问系统总线
然后设备控制器和内存之间
直接进行数据交换
这种方式呢 它的特点是
CPU可以在数据传输的过程当中干别的
不受影响
当然它的开始和结束也需要CPU的参与
这时候它适用于高吞吐量的设备I/O
这是我们CPU和系统之间的
两种数据传输方式
我们在这儿
再用磁盘数据读取这个过程
来细化一下
看它的交流过程是什么样子的
首先我们看到
这是我们系统里的连线图
CPU通过系统总线
连到内存和DMA控制器
然后DMA控制器
通过PCI总线连到我的磁盘设备
我们在这里
一次磁盘读取过程是什么样的
CPU在执行用户代码的过程当中
会产生磁盘读取请求
这个请求转到设备驱动
在内核里执行
设备驱动需要我把磁盘上的
什么地方的数据
读到内存的什么地方去
这个设备请求就会转换成
对磁盘控制器的操作
这个操作导致
磁盘控制器开始读取数据
读取数据之后初始化DMA传送
然后把数据通过PCI总线
传到DMA控制器
然后DMA控制器
再把数据传到内存的指定区域
也就是我们这里这个X
完成传送之后
它产生一个中断请求
CPU响应这个中断请求
来判断我最后这个操作是否结束
最后呢回到应用程序里
这是通过DMA和中断的方式
来完成磁盘数据读取的这个过程
另外还有一个方向是说
设备如何通知CPU
如何通知操作系统
在这里操作系统需要知道设备的状态
完成时间
比如说遇到的错误之类的
然后在这儿有两种方式
一种是轮询 一种是设备中断
我们在这里一个一个来讨论
轮询是指I/O设备上定义了
一组状态和控制寄存器
操作系统定期的检查这些状态寄存器
从而知道设备的状态
比如说我的数据是否发送完了
我的缓冲区是否还有空地儿
或者说我的缓冲区里是否有数据
这种做法相对来说它是简单的
但是如果你在这里操作频繁
多长时间会产生一次 不可预测的话
那么这时候开销和延时都比较大的
在这里开销大是说
我需要频繁进行操作
延时大是因为我不知道
我什么时候能知道设备状态的改变
我只能在我查的时候才能知道
如果说设备状态改变之后
很长一段时间没有去查
这个延时就大了
所以这是第一种方式
第二种方式是设备中断
在这种方式里头
CPU布置好I/O操作之后
它就可以去忙活别的了
然后这时候I/O设备
进行相应的I/O请求处理
处理完之后 产生中断
触发CPU 让CPU响应
CPU接收中断
然后执行相应的中断处理例程
这是它的一个交互过程
那么在这个交互过程当中
它是处理不可预知事件效果比较好
只要你一产生中断
CPU马上就能给出响应
原因在于CPU是在每两条指令执行期间
会去检查一次是否有中断请求
如果中断比较多
那这时候CPU被中断的频率就会比较高
这时候它的开销相对来说
和DMA方式传送数据的时候
它的开销也是大的
实际的做法是什么呢
会是在一些高速设备
会把两种办法结合起来
比如说在我们这里的高速网络设备
第一次的时候
它是采用中断方式来进行响应的
如果有数据包的接收
那这时候呢
CPU会响应中断来处理这条数据
由于输入输出数据比较多 量比较大
那这时候第一次中断处理完
相应的数据之后它会再进行轮询
如果有数据马上就要处理
这样的话后面就变成轮询方式了
一直到没有的时候 它才结束
下一次中间隔的时间比较长的时候
它再会转到中断方式
这是设备中断
下面我们具体来看一下
中断I/O的处理流程
首先是CPU在执行指令的过程当中
产生了I/O请求
这时候设备驱动会初始化这个I/O请求
当中的I/O控制器会初始化I/O操作
然后由设备进行相应的操作
操作完成或者出错
这时候它产生中断
CPU在完成I/O请求初始化之后
它就可以去干别的了
这时候它在每执行一条指令之后
它会检查中断请求
如果不做这个检查的话
那你这边有请求之后
它是不能做到及时响应的
正是由于CPU在设计上就已经做到了
用硬件来检查每一条指令执行期间
是否有中断请求 如果有
它就不去进行下一条指令的执行
而转到中断的处理
那么这时候CPU接收到中断请求之后
在当前指令结束之后
它就可以来进行这个响应
所以你这个延时通常是
最长是一条指令的执行时间
那么收到这个请求之后
它分发给相应的中断服务例程
由相应的中断服务例程进行处理
这是它的处理
处理完毕之后
CPU恢复被中断的进程的执行
在这个执行的过程当中
又可能执行到某一个地方去
再产生新的I/O请求
这是基于设备中断的
I/O请求的处理过程
有了这些描述之后
I/O的数据传输的方式和流程
我们就说清楚了