- 作者: 雪山肥鱼
- 时间:20210624 05:44
- 目的:I/O device
# I/O device
# 系统架构
# 标准设备结构
# 标准协议
# 中断
## 中断与轮询的平衡点
# DMA
# OS 与 设备的通信
# 设备驱动
## 简单IDE驱动程序举例
I/O device
介绍文件系统之前,需要对I/O设备有初步的认识。要知道I/O设备是如何于OS进行交互的。
input/output => I/O. 一个程序必须有输入和输出。
问题核心
- 如何将I/O 整合到系统中
- I/O的主要机制
- 如何利用I/O
系统架构
即I/O device 是如何融入整个系统中的
系统架构.png
- CPU 和 内存通信 走专用内存总线
- 图像及一些高性能设备通过pci总线 连接 内存总线
- 外部总线,SCSI, SATA,USB等内部外部设备
标准设备结构
I/O device 结构.png由图可知 ,I/O device 分为两部分
- Interface
提供对外接口,对外我的理解是针对 os/apps. 暴露给外的原因很明确,我需要让对接我的人,知道我的一下信息,这些信息都存在寄存器中
- 状态(是否可以开始接受和传输)
- Command(接头人让我做什么)
- Data (数据传输)
- 设备自己的内部结构
- 微型CPU
- 内存
- 其他的硬件特定芯片
标准协议
协议其实很简单:
While(STATUS == BUSY)
; wait until device is not busy
Write data to DATA register
Write command to COMMAND register
; doing so starts the device and execute the command
While(STATUS == BUSY)
; wait until device is done with your request
总结来说就是4步流程:
- OS 会 轮询(polling) 设备,去得到设备的status
- status 不忙后,传送数据 (CPU会参与数据传输即 programmed I/O)
数据的传输实际上是非常耗CPU的 - 告知 device 应该执行什么command
- 切换设备状态为 busy
上述流程的问题非常明显,即 OS会轮询设备的状态,非常消耗 CPU 占用率。如何避免呢?
中断
核心思路是OS跟设备说,你数据传输好了,告诉我一下。(因为设备处理数据的速度远逊于CPU,所以很慢, 需要CPU去等。)
OS跟设备说的这句话含义是:
- OS 会给设备发一起请求(告诉我一下)
- OS 对自己留下笔记,到时候我该如何处理返回数据(即,注册ISR 服务内容)
- 发出请求后,OS做其他事情去了
- 设备完成数据处理后,返回结果,会告知OS(因为OS在step1中,提前注册了请求)
- OS 回头处理。
- 怎么处理呢? 进入 step2 中提前预定好的ISR 中断服务中。
中断的引入,提供了I/O复用的概念
-
无中断工作流
无中断.png
发生I/O时,比如CPU将数据及command指令发送给DISK,DISK的状态切换为busy, CPU则一直处于轮询 polling状态。
-
中断工作流
中断.png
很明显,CPU去做其他事情了。
中断与轮询的平衡点
中断的cpu利用率是明显高于无中断的。但万事具有两面性。
中断适合那些 device I/O 处理数据速度慢的情况。
如果遇到 device I/O 处理数据速度快,反而不是好事。如网络中收包。当要处理大量网络数据包时,频繁的中断,会让OS忙于上下文的切换,反而会降低速度处理速度,而且容易出现活锁的现象。即OS总是在处理上下文切换,并没有运行apps中的任何代码。也就是OS对Apps的请求无响应。
所以可以尝试找到平衡点,让轮询和中断的混用。
中断的另一个优化是合并,device在发出中断前会等待一会,再次浅见,其他对于 device的 请求可能也会完成。则多次中断可以合并成一次中断抛出。但是 中断等待的时间太长的话,又有增加app的请求延迟。这又是需要选择折中的地方
DMA
其实在 PI/O(即CPU参与 与 device的数据交互) 时非常占用CPU的使用率的。但对于CPU来说, 数据的copy都是琐碎的小事。
workflow 如下:
数据copy.png
DMA : direct memory access. 外部设备,直接通过DMA 与内存进行交互,DMA是不经过CPU的。当DMA与disk完成交互,会引发中断,让os介入,引发中断。
DMA workflow.png
OS 与 设备的通信
- 明确的I/O 指令
in 与 out 特权 指令 - 内存映射
硬件将设备寄存器以地址的方式映射到内存。当要访问设备寄存器时,操作系统装在或者存入到该内存地址,然后硬件会将装载/存入转移到设备上,而不是物理内存。
设备驱动
设备依靠设备驱动,才能真正的与OS合体。
在最底层,OS会有一部分里子软件清晰的知道硬件设备是如何工作的。这些里子软件就是设备驱动。所有OS与设备交互的细节全部封装与此。
以linux文件系统的来举例。
文件系统对于底层的硬件完全是不感知的,我只要给硬件通用块接口读写协议, 底层硬件可以识别这些协议,完成对应操作就完事儿了。
不管你硬盘用的SCSI,SATA,还是USB存储设备,对外你通过设备驱动,暴露给OS能够操作块的协议接口就行了。
所以,如果想要让OS识别硬件,则硬件接入时,必须安装相关驱动
通用的对外协议接口也会有一点瑕疵,即存储设备特殊的功能api,反而不支持。
驱动成簇的艾玛在内核中占有相当打的比例。
网友评论