操作系统之输入输出系统

设备控制器

电脑可以接入很多的输入输出设备(I/O 设备),如键盘、鼠标(输入)、显示器,打印机,音响(输出),U盘,硬盘(输入输出)等。
为了解决设备之间的差异性,每种设备都有一个设备控制器(硬件),⽐如硬盘有硬盘控制器、显示器有视频控制器等。
在这里插入图片描述
CPU 是通过设备控制器来和设备打交道的,这些控制器都很清楚的知道对应设备的⽤法和功能

设备控制器有自己的寄存器,CPU是通过(写入和读取这些寄存器)与设备控制器进行通信的:

  • 通过写⼊这些寄存器,操作系统可以命令设备发送数据、接收数据、开启或关闭,或者执⾏某些其他操作。
  • 通过读取这些寄存器,操作系统可以了解设备的状态,是否准备好接收⼀个新的命令等。

控制器中有三类寄存器,它们分别是数据寄存器、 命令寄存器以及状态寄存器:
在这里插入图片描述

  • 数据寄存器:CPU 向 I/O 设备写⼊需要传输的数据,⽐如要打印的内容是「Hello」,CPU 就要先发 送⼀个 H 字符给到对应的 I/O 设备。
  • 命令寄存器:CPU 发送⼀个命令,告诉 I/O 设备,要进⾏输⼊/输出操作,于是就会交给 I/O 设备去⼯作,任务完成后,会把状态寄存器⾥⾯的状态标记为完成。
  • 状态寄存器:⽬的是告诉 CPU ,现在已经在⼯作或⼯作已经完成,如果已经在⼯作状态,CPU 再发送数据或者命令过来,都是没有⽤的,直到前⾯的⼯作已经完成,状态寄存标记成已完成,CPU 才能发送下⼀个字符和命令。

输⼊输出设备(I/O设备)可分为两⼤类 :块设备和字符设备

  • 块设备:把数据存储在固定⼤⼩的块中,每个块有⾃⼰的地址,硬盘、USB 是常⻅的块设备。
    块设备通常传输的数据量会⾮常⼤,于是控制器设⽴了⼀个可读写的数据缓冲区: CPU 写⼊数据到控制器的缓冲区时,当缓冲区的数据囤够了⼀部分,才会发给设备。同样,CPU 从控制器的缓冲区读取数据时,也需要缓冲区囤够了⼀部分,才拷⻉到内存。

刚才说了,CPU是通过写入和读取设备控制器中的寄存器与设备控制器进行通信的,而CPU又是通过设备控制器来和设备打交道的,那么回到根源,CPU又是怎么和设备的控制寄存器和数据缓冲区进⾏通信的呢?

  1. 端⼝ I/O,每个控制寄存器被分配⼀个 I/O 端⼝,可以通过特殊的汇编指令操作这些寄存器,⽐如in/out 类似的指令
  2. 内存映射 I/O,将所有控制寄存器映射到内存空间中,这样就可以像读写内存⼀样读写数据缓冲区。

CPU与输入输出设备通信过程:
在这里插入图片描述
在这里插入图片描述

中断处理和DMA

当 CPU 让设备控制器去读设备的数据,它读完的时候,要怎么通知CPU 呢?

中断:当设备控制器通知CPU数据已经准备好了。⼀般会有⼀个中断控制器(硬件),当设备完成任务后触发中断到中断控制器,中断控制器就通知 CPU,⼀个中断产⽣了,CPU 需要停下当前⼿⾥的事情来处理中断。

注:中断控制器通知 CPU
(设备发送中断来通知操作系统,操作系统中处理中断的地⽅就在设备驱动程序⾥,它会及时响应控制器发来的中断请求,并根据这个中断的类型调⽤响应的中断处理程序进⾏处理。这个会在后面讲)

中断有两种,⼀种软中断,例如代码调⽤ INT 指令触发,⼀种是硬件中断,就是硬件通过中断控制器触发的。

但中断的⽅式对于频繁读写数据的磁盘,并不友好,这样 CPU 容易经常被打断,会占⽤ CPU ⼤量的时间。对于这⼀类设备的问题的解决⽅法是使⽤ DMA(Direct Memory Access) 功能,它可以使
得设备在CPU 不参与的情况下,能够⾃⾏完成把设备 I/O 数据放⼊到内存。那要实现 DMA 功能要有 「DMA 控制器」硬件的⽀持。

在这里插入图片描述

DMA 的⼯作⽅式如下:

  • CPU 需对 DMA 控制器下发指令,告诉它想读取多少数据,读完的数据放在内存的某个地⽅就可以了;
  • 接下来,DMA 控制器会向磁盘控制器发出指令,通知它从磁盘读数据到其内部的缓冲区中,接着磁盘控制器将缓冲区的数据传输到内存;
  • 当磁盘控制器把数据传输到内存的操作完成后,磁盘控制器在总线上发出⼀个确认成功的信号到DMA 控制器;
  • DMA 控制器收到信号后,DMA 控制器发中断通知 CPU 指令完成,CPU 就可以直接⽤内存⾥⾯现成的数据了;

CPU 当要读取磁盘数据的时候,只需给 DMA 控制器发送指令,然后返回去做其他事情,当磁盘数据拷⻉到内存后,DMA 控制机器通过中断的⽅式,告诉 CPU 数据已经准备好了,可以从内存读数据了。仅仅在传送开始和结束时需要 CPU ⼲预

DMA控制器:DMA(Direct Memory Access)控制器是一种在系统内部转移数据的独特外设,可以将其视为一种能够通过一组专用总线将内部和外部存储器与每个具有DMA能力的外设连接起来的控制器。它之所以属于外设,是因为它是在处理器的编程控制下来 执行传输的。

设备驱动程序

虽然设备控制器(硬件)屏蔽了设备的众多细节,但每种设备的控制器的寄存器、缓冲区等使⽤模式都是不同的,所以为了屏蔽「设备控制器」的差异,引⼊了设备驱动程序(属于操作系统)
在这里插入图片描述
设备控制器不属于操作系统范畴,它是属于硬件,⽽设备驱动程序属于操作系统的⼀部分。
操作系统的内核代码可以像本地调⽤代码⼀样使⽤设备驱动程序的接⼝,⽽设备驱动程序是⾯向设备控制器的代码,它发出操控设备控制器的指令后,才可以操作设备控制器。

一句话,用户通过调用操作系统中的设备驱动程序接⼝来操控设备控制器

不同的设备控制器虽然功能不同,但是设备驱动程序会提供统⼀的接⼝给操作系统,这样不同的设备驱动程序,就可以以相同的⽅式接⼊操作系统

前⾯提到了不少关于中断的事情,设备完成了事情,则会发送中断来通知操作系统。那操作系统就需要有⼀个地⽅来处理这个中断,这个地⽅也就是在设备驱动程序⾥,它会及时响应控制器发来的中断请求,并根据这个中断的类型调⽤响应的中断处理程序进⾏处理。

通常,设备驱动程序初始化的时候,要先注册⼀个该设备的中断处理函数
在这里插入图片描述
完整中断处理程序的处理流程如下:

  1. 在 I/O 时,设备控制器如果已经准备好数据,则会通过中断控制器向 CPU 发送中断请求;
  2. 保护被中断进程的 CPU 上下⽂;
  3. 转⼊相应的设备中断处理函数;
  4. 进⾏中断处理;
  5. 恢复被中断进程的上下⽂;

下面聊一聊Linux系统中的一些设计

通⽤块层

对于块设备,为了减少不同块设备的差异带来的影响,Linux 通过⼀个统⼀的通⽤块层(Window有没有网上没看到相关的答案,暂且认为这是Linux 独有的),来管理不同的块设备

通⽤块层是处于⽂件系统和磁盘驱动(块设备)中间的⼀个块设备抽象层,它主要有两个功能:

  • 第⼀个功能,向上为⽂件系统和应⽤程序,提供访问块设备的标准接⼝,向下把各种不同的磁盘设备抽象为统⼀的块设备,并在内核层⾯,提供⼀个框架来管理这些设备的驱动程序;
  • 第⼆功能,通⽤层还会给⽂件系统和应⽤程序发来的 I/O 请求排队,接着会对队列重新排序、请求合并等⽅式,也就是 I/O 调度,主要⽬的是为了提⾼磁盘读写的效率。

Linux 内存⽀持 5 种 I/O 调度算法,分别是:

  • 没有调度算法

  • 先⼊先出调度算法

  • 完全公平调度算法

  • 优先级调度

  • 最终期限调度算法

第⼀种,没有调度算法,是的,你没听错,它不对⽂件系统和应⽤程序的 I/O 做任何处理,这种算法常⽤在虚拟机 I/O 中,此时磁盘 I/O 调度算法交由物理机系统负责。
第⼆种,先⼊先出调度算法,这是最简单的 I/O 调度算法,先进⼊ I/O 调度队列的 I/O 请求先发⽣。
第三种,完全公平调度算法,⼤部分系统都把这个算法作为默认的 I/O 调度器,它为每个进程维护了⼀个I/O 调度队列,并按照时间⽚来均匀分布每个进程的 I/O 请求。
第四种,优先级调度算法,顾名思义,优先级⾼的 I/O 请求先发⽣, 它适⽤于运⾏⼤量进程的系统,像是桌⾯环境、多媒体应⽤等
第五种,最终期限调度算法,分别为读、写请求创建了不同的 I/O 队列,这样可以提⾼机械磁盘的吞吐量,并确保达到最终期限的请求被优先处理,适⽤于在 I/O 压⼒⽐较⼤的场景,⽐如数据库等。

存储系统 I/O 软件分层

前⾯说到了不少东⻄,设备、设备控制器、驱动程序、通⽤块层,现在再结合⽂件系统原理,我们来看看Linux 存储系统的 I/O 软件分层。

可以把 Linux 存储系统的 I/O 由上到下可以分为三个层次,分别是⽂件系统层、通⽤块层、设备层。他们整个的层次关系如下图:
在这里插入图片描述
这三个层次的作⽤是:

  • ⽂件系统层,包括虚拟⽂件系统和其他⽂件系统的具体实现,它向上为应⽤程序统⼀提供了标准的⽂件访问接⼝,向下会通过通⽤块层来存储和管理磁盘数据。
  • 通⽤块层,包括块设备的 I/O 队列和 I/O 调度器,它会对⽂件系统的 I/O 请求进⾏排队,再通过 I/O调度器,选择⼀个 I/O 发给下⼀层的设备层。
  • 设备层,包括硬件设备、设备控制器和驱动程序,负责最终物理设备的 I/O 操作。

还可以分为用户空间,内核空间物理硬件三层,如上图所示

有了⽂件系统接⼝之后,不但可以通过⽂件系统的命令⾏操作设备,也可以通过应⽤程序,调⽤
read 、 write 函数,就像读写⽂件⼀样操作设备,所以说设备在 Linux 下,也只是⼀个特殊的⽂件。

但是,除了读写操作,还需要有检查特定于设备的功能和属性。于是,需要 ioctl 接⼝,它表示输⼊输出控制接⼝,是⽤于配置和修改特定设备属性的通⽤接⼝。

另外,存储系统的 I/O 是整个系统最慢的⼀个环节,所以 Linux 提供了不少缓存机制来提⾼ I/O 的效率。

  • 为了提⾼⽂件访问的效率,会使⽤⻚缓存、索引节点缓存、⽬录项缓存等多种缓存机制,⽬的是为了减少对块设备的直接调⽤。
  • 为了提⾼块设备的访问效率, 会使⽤缓冲区,来缓存块设备的数据。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值