操作系统入门 – 设备管理
1.设备控制器
1.1 意义
电脑本身可以外接多个输入输出设备,如键盘、鼠标、显示器等。由于这些设备的功能和特性不同,但是又需要由操作系统同一管理。为了屏蔽每个设备之间的差异,引入了设备控制器。设备控制器是CPU与其他外围硬件进行通信和操作的工具。其大致可以分为状态寄存器、命令寄存器和数据寄存器。
1.2 寄存器的功能
- 数据寄存器:CPU向I/O设备写入需要传输的数据。
- 命令寄存器:CPU向I/O设备发送的执行指令,告知I/O需要执行什么操作。
- 状态寄存器:告知CPU设备的工作状态。
1.3 输入输出
在计算机中,输入输出可以分为 块设备 和 字符设备 。
- 块设备:把数据存储在固定大小的块中,每个块有自己的地址。例如硬盘、USB就是块设备。
- 字符设备:以字符为单位发送或接收一个字符流,字符设备时无法寻址的,也没有寻道操作。例如鼠标。
2.I/O控制方式
2.1 控制方式
之前我们有了解过,外围设备在执行操作时会采用中断的方式请求系统资源,但是中断对于频繁读写数据的硬盘来说就不太适合,会占用CPU大量时间。因此引入DMA功能。DMA功能可以保证设备在CPU不参与的情况下,自行完成把I/O数据放入内存。本节着重了解DMA
2.1 DMA工作方式
-
- CPU需要多DMA下发指令,告知读取数据的大小和读取完毕后数据存放位置。
-
- 此时DMA会向磁盘控制器发出指令,通知磁盘读取数据到内部缓冲区,之后磁盘控制器将缓冲区数据传入内存。
-
- 数据传输完成后,磁盘控制器在总线上发出一个确认成功的信号到DMA控制器中。
-
- DMA收到信号后会使用中断通知CPU。
从上述流程中可以看到,当CPU想要获取外围硬件中的数据时,只需向DMA发送指令即可,当外围硬件数据处理完成后会由DMA通知CPU,避免了数据频繁交换时对CPU的中断。
3.设备驱动器
3.1 意义
设备控制器能够屏蔽许多问题,但不懂控制器的寄存器、缓冲区都是不一样的。为了消除其间的差异,引入设备驱动器的概念
3.2 区别
设备控制器时存在余外围设备的硬件上,而设备驱动器则是操作系统中的一部分。设备驱动器将会提供统一接口给操作系统,因此不同的设备驱动程序就可以以相同方式接入操作系统。
3.3 处理方式
前文中提到设备完成指令后会产生中断,而中断响应的地方就是设备驱动器中。它会及时响应控制器发来的中断请求,并根据这个中断的类型调用响应的中断处理程序进行处理。中断处理流程如下:
-
- 在 I/O 时,设备控制器如果已经准备好数据,则会通过中断控制器向 CPU 发送中断请求;
-
- 保护被中断进程的 CPU 上下文;
-
- 转入相应的设备中断处理函数;
-
- 进行中断处理;
-
- 恢复被中断进程的上下文;
4.通用块层
4.1 意义
在Linux中为避免不同块层设备之间造成的不同影响,使用通用块层来解决这一问题。简单来说通用块层是处于文件系统和磁盘驱动中间的一个块设备抽象层。
4.2 功能
- 向上为文件系统和应用程序,提供访问块设备的标准接口,向下把各种不同的磁盘设备抽象为统一的块设备,并在内核层面,提供一个框架来管理这些设备的驱动程序;
- 通用层还会给文件系统和应用程序发来的 I/O 请求排队,接着会对队列重新排序、请求合并等方式,也就是 I/O 调度,主要目的是为了提高磁盘读写的效率。
5.存储系统I/O软件分层
5.1 分层
在Linux中可以将存储系统的 I/O 由上到下可以分为三个层次,分别是文件系统层、通用块层、设备层。其作用如下:
- 文件系统层,包括虚拟文件系统和其他文件系统的具体实现,它向上为应用程序统一提供了标准的文件访问接口,向下会通过通用块层来存储和管理磁盘数据。
- 通用块层,包括块设备的 I/O 队列和 I/O 调度器,它会对文件系统的 I/O 请求进行排队,再通过 I/O 调度器,选择一个 I/O 发给下一层的设备层。
- 设备层,包括硬件设备、设备控制器和驱动程序,负责最终物理设备的 I/O 操作
6.例子 ———— 键盘输入
CPU 里面的内存接口,直接和系统总线通信,然后系统总线再接入一个 I/O 桥接器,这个 I/O 桥接器,另一边接入了内存总线,使得 CPU 和内存通信。再另一边,又接入了一个 I/O 总线,用来连接 I/O 设备,比如键盘、显示器等。
那当用户输入了键盘字符,键盘控制器就会产生扫描码数据,并将其缓冲在键盘控制器的寄存器中,紧接着键盘控制器通过总线给 CPU 发送中断请求。
CPU 收到中断请求后,操作系统会保存被中断进程的 CPU 上下文,然后调用键盘的中断处理程序。
键盘的中断处理程序是在键盘驱动程序初始化时注册的,那键盘中断处理函数的功能就是从键盘控制器的寄存器的缓冲区读取扫描码,再根据扫描码找到用户在键盘输入的字符,如果输入的字符是显示字符,那就会把扫描码翻译成对应显示字符的 ASCII 码,比如用户在键盘输入的是字母 A,是显示字符,于是就会把扫描码翻译成 A 字符的 ASCII 码。
得到了显示字符的 ASCII 码后,就会把 ASCII 码放到「读缓冲区队列」,接下来就是要把显示字符显示屏幕了,显示设备的驱动程序会定时从「读缓冲区队列」读取数据放到「写缓冲区队列」,最后把「写缓冲区队列」的数据一个一个写入到显示设备的控制器的寄存器中的数据缓冲区,最后将这些数据显示在屏幕里。
显示出结果后,恢复被中断进程的上下文。