I/O 与磁盘

I/O

I/O 是计算机科学中的一个常见缩写,它代表了输入/输出(Input/Output)的意思。在计算机系统中,I/O 涉及到计算机与外部设备之间的数据传输。输入通常是指从外部设备(如键盘、鼠标、磁盘驱动器、网络等)传输数据到计算机系统,而输出是指从计算机系统传输数据到外部设备。

I/O 是操作系统中非常复杂的一个话题,因为其牵涉到相当多部分。

计算机系统中不同操作的延迟或响应时间的估计数字:

Latency numbers for the 2020s

  1. 内存访问延迟: 访问计算机内存通常是非常快的操作,延迟通常在纳秒级别(几十纳秒或更短)。这意味着从内存读取或写入数据的速度非常快。

  2. 磁盘 I/O 延迟: 与内存相比,访问磁盘通常更慢。典型的磁盘读取操作可能需要几毫秒(毫秒)的时间,具体取决于磁盘驱动器的类型和性能。

  3. 网络通信延迟: 网络通信延迟取决于网络延迟和带宽,通常在几毫秒到数十毫秒之间。这包括发送数据到远程服务器和接收响应的时间。

常见 I/O 设备传输效率

计算机存储结构

下图展示了典型现代计算机系统的数据存储结构以及 I/O 在该结构中的位置:

  1. 寄存器(Registers)是计算机系统中最快速、最小的存储设备之一,用于存储和处理数据。它们通常位于中央处理单元(CPU)内部,并用于执行计算和控制指令。由于其极高的速度,寄存器在执行计算和控制任务时起到关键作用,而且在 CPU 设计和程序优化中具有重要意义。

  2. 高速缓存(Cache)是计算机系统中用于提高数据访问速度和性能的关键组件。它是一种快速存储器,用于存储最常用的数据,以减少对较慢存储器(如主内存或硬盘驱动器)的访问次数。

    计算机系统通常采用多层内存层次结构,其中包括高速缓存、主内存和较慢的外部存储器(如硬盘驱动器)。高速缓存位于主内存和中央处理单元(CPU)之间,具有不同级别,如一级缓存(L1)、二级缓存(L2)、三级缓存(L3)等。

  3. 动态随机访问存储器(Dynamic Random-Access Memory,DRAM)的缩写,它是计算机系统中广泛使用的主要内存类型之一。DRAM 是一种易失性存储器,用于存储计算机程序和数据,但它需要不断刷新以保持数据的完整性。与 CPU 缓存不同,DRAM 的容量通常较大,但速度较慢。

  4. 次级存储(Secondary storage)是计算机系统中的一种主要存储层级,用于长期数据存储和备份。与主内存(RAM)不同,它通常是非易失性的,意味着数据在断电后仍然保持完好。次级存储包括各种设备和媒体,例如硬盘驱动器(HDD)、固态硬盘(SSD)、光盘(如 CD 和 DVD)、磁带、USB 闪存驱动器、网络附加存储(NAS)以及云存储服务等。

    • 硬盘驱动器(Hard Disk Drive,HDD)是一种常见的计算机数据存储设备,用于长期数据存储和检索。HDD 使用旋转的磁性盘片和机械臂来读写数据。

      HDD 内部包含一个或多个盘片(通常是金属或玻璃制成),盘片上分成了一系列磁性轨道和扇区。数据以磁性方式存储在这些表面上。机械臂负责将读/写头移动到正确的磁道上来读取或写入数据。磁头将数据编码为磁性位,然后根据需要将其读取或写入。

    • 固态硬盘(Solid-State Drive,SSD)是一种用于数据存储的非机械式存储设备。SSD 是一种高性能、可靠、耐用且节能的数据存储解决方案,它已经取代了许多传统的 HDD,并成为现代计算机和移动设备的标配之一。

  5. I/O 控制器(I/O Controller),是计算机系统中的硬件组件,用于管理和协调输入和输出设备的数据传输和通信。I/O 控制器起到桥梁的作用,协调主处理器(CPU)与外部设备之间的数据交换。不同类型的 I/O 控制器针对不同类型的设备,如存储设备、网络设备和外围设备等,都具有特定的功能和特点。

I/O 传输

I/O bus

I/O 总线(I/O Bus)是计算机体系结构中的一个关键组成部分,用于传输数据和控制信息,以连接计算机主板上的主处理器(CPU)和内存与外部设备之间。I/O总线是计算机系统内部的物理或电子通道,它允许不同类型的输入/输出设备与计算机进行通信,包括硬盘驱动器、键盘、鼠标、显示器、打印机、USB 设备和网络适配器等。

总得来说,我们可以认为 I/O 总线由两部分组成:

  • 一组连接设备用于数据传输的线(Wires)
  • 数据传输操作的协议(Protocols)

不同类型的计算机和体系结构可能使用不同的 I/O 总线标准,如 PCI(Peripheral Component Interconnect)、PCI Express、USB、SATA 等。这些标准规定了总线的电气和物理规格,以确保设备的互操作性。

PCI 架构

  • PCI Bus(Peripheral Component Interconnect Bus)

    PCI 是一种高性能总线标准,最早于1992年引入,并经过多次更新和改进。PCI 总线具有较高的数据传输速度和带宽,通常适用于连接高性能设备,如图形卡等等。

  • SCSI Bus(Small Computer System Interface Bus)

    SCSI 是一种用于连接计算机和外部设备的标准接口。它最早出现于1980年代。现在 SCSI 总线用于连接各种类型的设备,包括硬盘驱动器、光盘驱动器、打印机、扫描仪、磁带驱动器等。它通常用于需要高性能和可靠性的存储设备。

操作系统与 I/O 的交互

操作系统和 I/O 设备之间的交互通常需要使用寄存器来管理和监控 I/O 操作的进展和状态。这些寄存器通常是硬件设备上的寄存器,用于记录设备的状态和控制信息。

  1. 状态寄存器(Status Register)

    状态寄存器通常包含设备的当前状态信息,如设备是否忙碌、是否就绪、是否有错误等。操作系统可以定期轮询这个寄存器来检查设备状态,以决定是否可以执行 I/O 操作。

    典型的状态位包括忙碌位(Busy)、错误位(Error)、就绪位(Ready)等。

  2. 数据寄存器(Data Register)

    数据寄存器用于实际的数据传输,包括从 CPU 发送数据到设备或从设备接收数据到 CPU。操作系统通过读取或写入数据寄存器来传递数据。我们可以认为数据寄存器充当了数据传输的临时存储区域,允许数据在不同硬件模块之间进行有效的交换。

  3. 命令寄存器(Command Register)

    命令寄存器包含了控制 I/O 设备的命令码。这些命令码告诉设备要执行的操作,例如读取、写入、打开、关闭、复位等。通过命令寄存器,操作系统可以向设备发送启动或停止命令,以开始或终止 I/O 操作。

一个典型的操作系统与 I/O 交互的执行过程:

  1. 操作系统根据状态寄存器判断什么时候某个设备处于就绪状态(Ready);
  2. 若启动 I/O,则操作系统会向数据寄存器写入数据,并且设置命令寄存器的数据为我们需要的 I/O 操作的操作码(此时,I/O 控制器会设置该设备的状态寄存器为 Busy);
  3. I/O 控制器接下来读取命令寄存器数据寄存器的内容,并开始执行命令;
  4. 操作系统根据执行结果对状态寄存器进行修改:
  • 若正常执行结束,即所有指令都执行完成,控制器将清除该命令,并将其 Busy 状态复位
  • 若出现异常状态,则在必要情况下将状态寄存器设置为 Error
中断 & 轮询

在执行 I/O 操作时,操作系统需要知道:

  • 某个设备是否完成了 I/O 操作
  • 某个设备的特定 I/O 操作是否遇到了异常

这意味着 I/O 设备必须与 OS 实现有效通信。

  • I/O 中断(I/O Interrupt)

    当设备需要 CPU 的处理时,I/O 设备会生成一个中断信号,CPU 在接收到中断信号后立即暂停正在执行的任务,保存当前状态(通常通过将寄存器内容保存到堆栈),并跳转到中断处理程序。中断处理程序负责执行与中断相关的任务,然后返回到先前中断之前的任务。

    中断是异步的,它们随时可能发生,而不需要 CPU 连续地检查设备状态。

    • 优点:能较好地处理不可预判的异常(Great robustness)

    • 缺点:开销大(High overhead)

      这里的开销主要来自于 I/O 中断造成的上下文切换(Context switching)

  • 轮询(Polling)

    在轮询中,操作系统或应用程序周期性检查设备的状态寄存器,以查看是否需要处理。如果发现有事件发生,系统会采取相应的措施。

    • 优点:开销小(Low overhead)
    • 缺点:如果 I/O 操作不频繁或不可预测,则会在轮询上花费过多时间
设备驱动程序

设备驱动程序(Device Driver)是计算机软件的一部分,它允许操作系统与硬件设备进行通信。它的主要作用是作为操作系统和物理硬件设备之间的桥梁,使得操作系统可以控制和操作硬件。

设备驱动程序为操作系统提供了一个统一的接口,使得操作系统可以与各种各样的硬件设备进行交互,而不需要知道它们的具体细节。

编程 I/O & DMA

在解决状态访问的问题后我们还需要实现数据传输,常见的两种方法是编程 I/O 和直接内存访问。

  • 编程 I/O(Programmed I/O)

    编程 I/O(Programmed I/O)是计算机系统中的一种基本 I/O 操作方法,它通过 CPU 执行的程序来控制数据的传输和通信。在 Programmed I/O中,CPU 负责直接处理 I/O 操作,包括从外部设备读取数据或将数据写入外部设备。即编程 I/O 所有数据的传输都依托于处理器的指令

    • 优点:因为是从编程角度出发的,因此易于实现,对硬件需求低
    • 缺点:会消耗与数据大小成比例的处理器周期
  • 直接内存访问(Directly Memory Access,DMA)

    直接内存访问(Direct Memory Access,DMA),是一种计算机系统中用于提高数据传输性能的技术。DMA 允许外部设备(如硬盘驱动器、网络适配器、图形卡等)直接访问主内存,而无需 CPU 的直接干预,从而减少 CPU 的负担,提高数据传输效率。

    DMA 的具体过程

    1. 设备驱动程序被通知:首先,CPU 告诉设备驱动程序需要从磁盘将数据传输到内存中的某个缓冲区(地址 X)。
    2. 设备驱动程序通知磁盘控制器设备驱动程序随后指示磁盘控制器从磁盘传输 C 字节的数据到内存中的缓冲区(地址X)。
    3. 磁盘控制器启动 DMA 传输磁盘控制器开始 DMA 传输的过程
    4. 磁盘控制器与 DMA 控制器的交互:磁盘控制器将每一个字节发送到 DMA 控制器
    5. DMA 控制器传输数据DMA 控制器开始向缓冲区 X 传输字节,同时递增内存地址,并减少 C 的值,直到 C 变为 0。
    6. DMA 中断 CPU:当所有的数据都被传输完毕(即 C = 0)时,DMA 会发出一个中断信号给 CPU,告知其数据传输已经完成。

内存映射 I/O

内存映射 I/O(Memory-mapped I/O)是一种在计算机系统中用于管理 I/O 设备的通用方法,它允许操作系统和应用程序将 I/O 设备视为内存地址范围的一部分,使其可以直接读取和写入设备数据,就像操作内存一样。

在内存映射 I/O 中,每个 I/O 设备都被分配一个在物理内存地址空间中的范围。这个地址范围通常称为设备寄存器的地址空间,其中包含了与设备通信的特定寄存器(状态寄存器、数据寄存器、命令寄存器等等)和数据缓冲(Buffer)

注:该内存分配区域一般只用于 I/O 通信而不会进行其他操作

I/O 的四大类型

  • 同步阻塞 I/O(Synchronous Blocking I/O)

    最常见的 I/O 模型之一就是同步阻塞 I/O 模型。在这种模型中,用户空间应用程序执行一个系统调用,导致应用程序阻塞。这意味着应用程序会一直阻塞,直到系统调用完成(数据传输或出错)。调用应用程序处于不消耗 CPU 的状态,只是等待响应,因此从处理角度来看是高效的。

  • 同步非阻塞 I/O(Synchronous Non-blocking I/O)

    同步非阻塞 I/O 是同步阻塞的一个效率较低的变体。在这种模型中,设备以非阻塞方式打开。这意味着,与其立即完成一个 I/O 操作,读操作可能返回一个错误代码,表明命令不能立即得到满足(EAGAINEWOULDBLOCK)。

  • 异步阻塞 I/O(Asynchronous Blocking I/O)

    另一种阻塞范式是使用阻塞通知的非阻塞 I/O。在这种模型中,配置了非阻塞 I/O,然后使用阻塞的 select 系统调用来确定何时存在针对 I/O 描述符的任何活动。使 select 调用变得有趣的是,它可以用来为不只一个描述符提供通知,而是多个。对于每个描述符,你可以请求通知描述符写数据的能力、可读数据的可用性,以及是否发生了错误。

  • 异步非阻塞 I/O(Ansynchronous Non-blocking I/O)

    最后,异步非阻塞 I/O 模型是一个 I/O 与处理重叠的模型。读取请求立即返回,表示读取操作已经成功启动。应用程序随后可以在后台读取操作完成的同时执行其他处理。当读取响应到达时,可以生成一个信号或基于线程的回调来完成 I/O 事务。

一个 I/O 请求的生命周期

磁盘

磁盘(Disk)是计算机系统中用于存储数据的主要外部设备之一。磁盘是一种非易失性存储媒体,意味着数据会在断电或重启后仍然保留。

HDD

基本结构

硬盘驱动器(Hard Disk Drive,HDD)是一种用于存储数据的计算机存储设备。HDD 是一种机械式存储设备,其工作原理是使用旋转的磁性盘片和移动的读写磁头来读取和写入数据。

  1. 磁道(Track)
    • 磁道是硬盘驱动器上的一个圆形轨迹或路径,位于硬盘盘片的表面上;
    • 硬盘的每个盘片通常包含多个同心圆磁道,这些磁道从盘片的中心开始,向外扩展;
    • 每个磁道上的数据通常具有相似的物理位置,因此可以更快地被访问。
  2. 柱面(Cylinder)
    • 柱面是多个硬盘盘片上相同位置的磁道的集合;
    • 每个盘片上具有相同半径位置的磁道被组合成一个柱面;
    • 从柱面的角度来看,这些磁道在不同盘片之间对齐,因此它们可以一起被读取或写入,从而提高数据的传输速度。
  3. 扇区(Sector)
    • 扇区是磁道上的最小存储单位,通常包含 512 字节或更多数据;
    • 每个磁道被划分成多个扇区,以便更有效地存储和检索数据;
    • 操作系统和硬件通过扇区来访问硬盘上的数据。数据的读取和写入是以扇区为单位进行的。
时延分析

HDD 技术寻址并传输数据的时间开销我们可以认为由以下 3 部分组成:

  1. 寻道时间(Seek time):即移动磁头到目标所在柱面和磁道所花费的时间。寻道时间受到磁头移动的距离和速度的影响。较短的寻道时间表示硬盘可以更快地访问数据,因此是一个性能指标。
  2. 旋转延迟(Rotational delay):找到目标位置后需要旋转磁盘使得磁头落在目标扇区,这由磁盘盘片的旋转速度相关(单位:RPM,每分钟旋转次数)。
  3. 传输延迟(Transfer delay):使用读写头来传输数据。实际的数据传输时间取决于硬盘的数据传输速度。这通常以每秒字节(Bps)或兆字节每秒(MBps)来表示。

我们假设某个 HDD 设备的平均寻道时间是 5ms,盘片旋转速度为 7200 RPM,传输速率为 50 MB/s,一个数据块的大小为 4KB,则有:

  • 平均旋转延迟 = 盘片旋转一圈的时间 / 2 = 8ms / 2 = 4ms

  • 一个数据块的平均传输时间 = 4 KB / 50 MB/s = 0.08ms

进一步,我们可以得到:

  • 随机读取一个数据块的时间开销 = 平均寻道时间 + 平均旋转延迟 + 数据块传输延迟 = 9.08ms
  • 随机读取同一个柱面的某个数据块的时间开销 = 平均旋转延迟 + 数据块传输延迟 = 4.08ms
  • 读取同一个柱面同一个磁道的下一个数据块的时间开销 = 数据传输延迟 = 0.08ms
磁盘调度

由于 HDD 获取盘片速度较慢,所以我们当我们的任务队列中有多个任务时需要合适的调度策略来处理任务。

假设我们的任务队列当前有 6 个任务,每个任务所在磁道与盘片圆心的距离分别为 99,10,50,150,11,30。则这些任务在不同调度策略下的磁头移动方式如下:

FIFO

先来先服务(First In First Out,FIFO),即严格按照队列结构实行先进先出。

FIFO

优点:最公平。

缺点:由于任务位置可能是随机的,可能会花费很多寻道时间。

SSTF

最短寻道时间优先(Shortest Seek Time First,SSTF),即磁头每次都向最近的任务移动。

SSTF,假设磁头从 99 处开始

优点:利于减少寻道时间。

缺点:可能在调度出现某个任务长期未得到响应而造成饥饿。

Scan

Scan 调度,也叫电梯算法(Elevator algorithm),相比于 SSTF,Scan 策略每次只选择当前运动方向最近的请求。当完成磁道半径最大的请求后就会逆转当前方向。

Scan,假设磁头初始在 99 的位置,初始方向是由低磁道到高磁道

优点:避免了请求饥饿。

缺点:某些情况可能不够公平。(比如上图在磁道 10 处的请求)

C-Scan

C-Scan 调度,就是在 Scan 调度的基础上,不处理逆转方向过程中遇到的任何请求,这可以使得 C-Scan 调度相比于 Scan 调度而言更加公平。

C-Scan,假设磁头初始在 99 的位置,初始方向是由低磁道到高磁道

SSD

即固态硬盘(Solid State Drive,SSD),是一种用于数据存储的存储设备,它使用集成电路(Integrated circuits)来存储数据,而不像传统硬盘驱动器(HDD)那样使用旋转磁盘和机械臂来读写数据,SSD 中没有任何异动的机械器件。

SSD

由于不依赖机械臂读写数据,所以 SSD 读写数据就不再受到像 HDD 中的寻道时间和旋转延迟的限制。

NAND 闪存

在 SSD 中广泛使用 NAND 闪存(NAND cell flash memory)技术,其通过晶体管(Transistor)存储一个或多个 bit,通过此可以划分为两种类型:

  • SLC(Single Level Cell):每个存储单元只存储一个 bit。
    • 特点:快速、高耐用性(Endurance)、成本高
  • MLC(Multiple Level Cell):每个存储单元可以存储多个 bit,一般是 2 ~ 3。
    • 特点:相对较慢、低耐用性、成本低

有关耐用性:

SSD 中存储单元的擦除/写入次数是受到限制的,每次执行擦除和写入操作时,存储单元中的浮动栅承受一定的电荷和电压压力。随着时间的推移,这些操作会导致存储单元中的浮动栅逐渐受损,降低了其可靠性和性能。

MLC 闪存相对 SLC 而言更容易受到擦除/写入次数限制,因为它每个存储单元的擦除/写入次数较少。这意味着 MLC 闪存的寿命可能会较短,尤其在高度写入密集的应用中。

Flash 芯片结构

SSD 采用 Flash 芯片结构(Flash Chip Structure),其结构可以划分如下:

  • 一个芯片可以划分为多个块组(Banks)
    • 一个块组可以划分为多个块(Blocks)(e.g. 256KB)
      • 一个块可以划分为多个页(Pages)(e.g. 4KB)
SSD 中的读与写
  • 读取(Reading)
    • 操作单位:页(Page)
    • 运行时间大约 10ms,远快于 HHD
  • 写(Writing)
    • 每次在执行写操作前要先擦除数据(Erasing a block),具体操作如下:
      1. 将目标数据块的所有 bit 置为 1(1 ~ 2ms)
      2. 对相应的页执行写操作,将一些 bit 设置为 0(200ms 左右)

HDD vs SSD

  • 对于随机访问 I/O(Random-access I/O),SSD 具有更大的优势,因为其没有机械部件带来的时间开销。
  • 对于顺序访问 I/O(Sequential-access I/O),二者差距较小。
  • 相比于 HDD,SSD 质量更轻、功耗更少、运行噪声也更小。

I/O 与磁盘
https://goer17.github.io/2023/10/15/IO 与磁盘/
作者
Captain_Lee
发布于
2023年10月15日
许可协议