操作系统 持久性

本文将介绍操作系统对持久性的支持。

一、I/O 设备

1. 系统架构

典型系统的架构如图:

  • CPU 通过某种内存总线或互联电缆连接到系统内存
  • 显卡或者其它高性能 I/O 设备通过常规的 I/O 总线连接到系统
  • SCSI、SATA、USB 接口的设备通过外围 I/O 总线连接到系统

之所以这么做的原因是:考虑物理布局及造价成本。

首先,越快的总线越短,高性能的内存总线没有足够的空间连接太多设备;其次,高性能总线的造假非常贵。

因此,系统的设计采用分层架构,让要求高性能的设备离 CPU 更近,让要求较低的设备离 CPU 更远。

2. 标准设备及其接口

一个标准设备可以拆分如下:

  • 硬件接口

    • 状态寄存器:用于读取并查看设备的当前状态
    • 命令寄存器:用于通知设备执行某个具体任务
    • 数据寄存器:用于将数据传给设备或从设备读取数据

    同软件一样,硬件也需要一些接口,让系统软件可以对它进行控制

  • 内部接口

3. 交互 - 轮询

操作系统通知设备进行某项工作,并通过轮询的方式查询设备的处理状态,交互流程如下:

  • 操作系统反复读取状态寄存器,直到设备处于可以接受命令的就绪状态
  • 操作系统发送数据至数据寄存器
  • 操作系统将命令写入命令寄存器
  • 操作系统再次反复读取状态寄存器,直到设备执行完成命令

4. 交互 - 中断

通过中断这一机制,操作系统与设备交互时不再需要轮询,交互流程如下:

  • 操作系统通知设备进行某项工作
  • 操作系统让对应进程睡眠,切换进程进行其它任务
  • 当设备完成工作后,会抛出一个硬件中断,硬件中断将引发 CPU 跳转执行操作系统预先定义好的中断处理程序,该程序将唤醒处于睡眠状态的进程

5. 中断和轮询的优劣

中断并非总是比轮询好。

如果设备的速度较快,使用轮询,通常几次轮询就可以返回结果;使用中断,线程切换、中断处理都需要消耗不少的代价。

如果设备的速度较慢,此时使用中断更好。

由于无法预知设备的速度,可以考虑使用混合策略,先尝试轮询一小段时间,若未完成再使用中断。

二、简单文件系统

1. 文件系统的组成

简单文件系统由两部分组成:

  • 数据结构
  • 访问方法

2. 数据结构

简单文件系统的数据结构主要包含以下几个部分:

  • S:superblock;超级块,包含某些特定信息,例如文件系统类型、inode 表起始位置等
  • i、d:inode 位图、数据位图;用于指示 inode、数据块是否空闲
  • inodes:inode 表;用于存放每个文件的信息,包括文件放置于哪些数据块、文件大小、所有者、访问权限、修改时间等
  • 数据区域:用于存放用户数据的区域

3. 访问方法

(1) 读取文件

  • 打开文件:

    • 接收 open 指令

    • 查找文件的 inode,将其读入内存

      由于文件、文件夹的数据结构是树形的,因此查找是逐层查找

    • 在 inode 中读取文件的基本信息(权限信息、文件大小、数据块等)

    • 文件状态标为已打开

  • 读取文件:

    • 接收 read 指令
    • 从文件中读取

(2) 写入文件

  • 打开文件:

    同上

  • 写入文件:

    • 读取数据位图,获取未被使用的数据块
    • 将数据块的新使用情况写入数据位图
    • 将数据块的新信息写入 inode
    • 将数据写入数据块

参考

  • 操作系统导论