IO与存储
设备管理概述
设备管理是操作系统的重要组成部分
同其他管理来说,该部分内容比较复杂凌乱。因为设备种类繁多,各自有 着不同的特点,所以需要制定一个通用的、规范的管理框架、方法
设备管理方法:
- 操作系统直接操纵设备,例如直接程序控制、中断方式控制
- 间接操纵,例如DMA和通道方式
- 通过使用设备驱动程序,OS值需要指定标准,具体操纵设备的程序交给不同的制造商去开发
磁盘IO过程
int fd = open("/dev/something");
for (int i = 0; i < 10; i++){
fprintf(fd, "Count %d\n",i);
}
close(fd);
-
不论什么设备都是open, read, write, close,这些是操作系统为用户提供的统一接口。
-
不同的设备对应不同的文件(设备文件),设备文件中存放了设备的属性
IO系统组成
-
用户库函数接口
-
IO内核子系统
- IO调度(磁盘寻道)、缓冲(文件系统磁盘访问)、错误处理、保护
-
设备驱动程序(中断服务程序)
- 隐藏设备差异,为操作系统和设备提供商提供标准的接口
-
IO硬件
- 字符设备、块设备;读写;同步异步
IO控制方式
设备管理的主要任务之一是控制设备和内存或CPU之间的数据传送
程序直接控制(查询)方式
- 当某进程需要输入/输出数据时,由 CPU向设备控制器发出一条I/O指令启动设 备工作(对于输出操作,则CPU还要向数 据寄存器中存放输出数据);
- 在设备输入/输出数据期间,CPU不断 地循环进行查询设备状态寄存器的值(检 查I/O工作是否完成)。
- 若完成,对输入操作来说CPU则从数据 寄存器中取出数据,然后进行下一次的输 入/输出数据或结束。
中断控制方式
设备就绪了告诉CPU,然后中断
- 某带有IO请求的进程,发送IO请求后进入阻塞态,CPU就转而去执行其他进程
- 当IO设备准备就绪,IO控制器向CPU发送中断信号,CPU停止执行其他进程,启动中断服务程序,恢复某进程继续执行。
DMA(直接内存存取)
- 当一个进程要求设备输入数据时,CPU对DMA进行初始化工作:
- 存放数据的内存起始地址 - DMA控制器的内存地址寄存器
- 要输入数据的字节数- DMA控制器的传送字节数寄存器
- 控制字(中断允许、DMA启动位=1) -DMA控制器的控制状态寄存器
- 启动位被置1,则启动DMA控制器开始进行数据传输
- 该进程放弃CPU,进入阻塞等待状态,等待第一批数据输入完成。进程调度程序 调度其他进程运行。
- 由DMA控制器控制整个数据的传输。
- 当输入设备将一个数据送入DMA控制器的数据缓冲寄存器后,DMA控制器立即取代 CPU,接管数据地址总线的控制权(CPU工作周期挪用),将数据送至相应的内存 单元;
- DMA控制器中的传输字节数寄存器计数减1;
- 恢复CPU对数据地址总线的控制权;
- 第(3)步过程循环直到数据传输完毕。
- 当一批数据输入完成,DMA控制器向CPU发出中断信号,请求中断运行进程并转 向执行中断处理程序。
- 中断程序首先保存被中断进程的现场,唤醒等待输入数据的那个进程,使其变成 就绪状态,恢复现场,返回被中断的进程继续执行。
- 当进程调度程序调度到要求输入数据的那个进程时,该进程就到指定的内存地址 中读取数据进行处理。
通道方式
通道具有简单的CPU功能,可编程,可管理多个设备同时工作。从而真正实现了CPU 与外部设备的并行工作。
工作过程:
-
当一个进程要求输入输出数据时,CPU根据请求形成有关通道程序,然后执行输入 输出指令启动通道工作;
-
申请输入输出数据的进程放弃CPU进入阻塞等待状态,等待数据输入输出工作的完 成,于是进程调度程序调度其他进程运行;
-
通道开始执行CPU放在主存中的通道程序,独立负责外设与主存的数据交换;
-
当数据交换完成后,通道向CPU发出中断信号,中断正在运行的进程,转向中断处 理程序;
-
中断处理程序首先保护被中断进程的现场,唤醒申请输入输出的那个进程,使其变 为就绪状态,关闭通道,然后恢复现场,返回被中断的进程继续运行;
-
当进程调度程序调度到申请输入输出数据的那个进程时,该进程就到指定的内存地 址中进行数据处理。
通道和DMA相比
- 共同点:
- 都能实现IO设备和内存之间建立数据直传通路;
- 不同点:
- DMA只能实现固定的数据传送控制,而通道有自己的指令和程序,具有更强的独立 处理数据输入和输出的能力。
- DMA只能控制一台或者少数几台同类设备,而一个通道可以控制多台同类或者不同 的设备。
缓冲技术
目的:解决CPU和外设速度不匹配的矛盾,提高CPU与外设之间 的并行性,减少对CPU的中断频率
实现方法:
- 硬件缓冲:利用专门硬件寄存器作为缓冲区,一般由外设自带的专用寄存器构成
- 软件缓冲:借助操作系统的管理,在内存中专门开辟若干单元作为缓冲区
软件缓冲实现
单缓冲
在内存中开辟一个固定大小的区域作为缓冲区
- 外设和CPU交换数据时,先将被交换的数据写入缓冲区,然后再由需要 数据的CPU或外设从缓冲区中取出
- 该方式中,外设与CPU对缓冲区的操作是串行的
双缓冲
在内存中设置2个大小相同的缓冲区。
- 外设和CPU可以交替使用这2个缓冲区,从而在一定程度上实现并行交 换数据
环形缓冲
在内存中设置大小相等的多个缓冲区,并将它们链接成为一 个环形链表。
-
Head一直指向缓冲区链表的第一个缓冲区;
-
Full一直指向缓冲区链表中的第一个存满数据的缓冲区;
-
Empty一直指向缓冲区链表中的第一个空白的缓冲区。
-
初始化时:Head=Full=Empty,整个缓冲区链表为空;
-
使用过程中:当Full=Empty <==> 整个缓冲区链表为空。
缓冲池
缓冲池是有多个大小相同的缓冲区组成
- 池中的缓冲区是系统公共资源,所有进程均可以共享
- 池由系统管理程序统一管理,负责分配、回收工作
- 池中每个缓冲区既可以用于输入数据,也可以用于输出数据
工作流程:
- 当输入设备需要进行数据输入时,则从空缓冲队列的队首取下一个空缓冲区, 将它作为收容输入工作缓冲区,当它被输入装满数据后,则被链接到输入缓冲队列的队尾;
- 当某进程需要从缓冲池输入数据时,则从输入缓冲队列的队首取一个缓冲区作为提取输入工作缓冲区,该进程从中提取数据,取完后,则将该缓冲区链接到空缓 冲区队列的队尾;
- 当某进程需要输出数据到缓冲池时,则从空缓冲队列的队首取下一个空缓冲区, 将它作为收容输出工作缓冲区,该进程向该缓冲区中存放数据,当它被装满数据后, 则被链接到输出缓冲队列的队尾
- 当输出设备需要进行数据输出时,则从输出缓冲队列的队首取一个缓冲区作为 提取输出工作缓冲区,并从中提取数据输出,取完后,则将该缓冲区链接到空缓冲 区队列的队尾。
sync
-
Linux系统为了提高读写磁盘的效率,会先将数据放在一块buffer中,在写磁盘时并不是立即将数据写到磁盘中,而是先写入这块buffer中了,此时如果重启系统,就可能造成数据丢失,sync命令用来flush文件系统buffer,这样数据才会真正的写到磁盘中,并且 buffer才能够释放出来,sync命令会强制将数据写入磁盘中,并释放该数据对应的buffer,所以常常会在写磁盘后输入sync命令来将数据真正的写入磁盘。
-
如果不去手动的输入sync命令来真正的去写磁盘,Linux系统也会有两种 写磁盘的时机:
- kflush内核线程周期性的去写磁盘
- buffer已满不得不写
缓冲技术-SPOOLING
- SPOOL - Simultaneous Peripheral Operation On Line外部设备同时联机操作,又称假脱机操作。
- SPOOL是操作系统中采用的一项将独占设备改造成共享设备的技术。
- 实现方法:截获向某独享设备输出的数据,暂时保存到内存缓冲区或磁 盘文件中,并进行排队,之后逐个输出到外设上
- 实现这一技术的软、硬件系统称为SPOOL系统,或假脱机系统,或 SPOOLING系统。
IO设备管理总结
- 如何实现交互 -》 首先需要了解I/O的工作原理
- 从用户如何I/O开始 -》用户发送一个命令(read)
- 系统调用read -》 被展开成给一些寄存器发送命令的代码
- 发送完命令以后 -》 CPU轮询,或CPU干其它事情并等中断
- 中断方案最常见 -》 相比其他设备,CPU太快了
- 实现独享设备的共享 -》 假脱机系统(SPOOLING)
磁盘设备
磁盘IO:缓存队列-》控制器-》寻道-》旋转-》传输
习题
设一个磁盘的平均寻道时间为12ms,传输速率是200MB/s,控制器开销是 0.2ms,转速为每分钟5400转。求读写一个512KB大小数据块的平均磁盘访 问时间?
平均旋转延时 = 0.5/(5400转/分) = 0.0056秒 = 5.6ms
平均磁盘访问时间 = 平均寻道时间 + 平均旋转延时 + 传输时间 + 控制 器延时 = 12ms + 5.6ms + 512KB/(200MB/s) + 0.2ms = (12 + 5.6 + 2.5 + 0.2)ms = 20.3ms
磁盘调度
- 多个磁盘访问请求出现在请求队列需要调度
- 调度的目标是平均访问延迟小
- 寻道时间是主要矛盾
先来先服务磁盘调度FCFS
一个实例: 磁头开始磁道位置=53;请求队列=98, 183, 37, 122, 14, 124, 65, 67
最短寻道时间优先磁盘调度(SSTF)
继续该实例: 磁头开始位置=53;请求队列=98, 183, 37, 122, 14, 124, 65, 67
扫描/电梯算法磁盘调度(SCAN)
SCAN调度算法 = SSTF+中途不回折:每个请求都有处理机会。根据其特征,SCAN也被称为电梯算法!
继续该实例: 磁头开始位置=53;请求队列=98, 183, 37, 122, 14, 124, 65, 67
循环扫描磁盘调度(C-SCAN)
C-SCAN = SCAN+直接移到另一端:两端请求都能很快处理。
继续该实例: 磁头开始位置=53;请求队列=98, 183, 37, 122, 14, 124, 65, 67
C-LOOK磁盘调度
C-LOOK = CSCAN+向前看一看:前面没有请求就回移
继续该实例: 磁头开始位置=53;请求队列=98, 183, 37, 122, 14, 124, 65, 67
磁盘调度算法比较
优点 | 缺点 | |
---|---|---|
FCFS算法 | 公平、简单 | 平均寻道距离大,仅应用在磁盘 I/O较少的场合 |
SSTF算法 | 性能比“先来先服务”好 | 不能保证平均寻道时间最短,可能 出现“饥饿”现象 |
SCAN算法 | 寻道性能较好,可避免“饥饿”现象 | 不利于远离磁头一端的访问请求 |
C-SCAN算法 | 消除了对两端磁道请求的不公平 | 两端没有访问请求时不必要移动到 头 |
C-LOOK算法 | 消除了两端不必要的移动 | 没有 |
磁盘编址
对磁盘的扇区进行编号,扇区=头+数据区+尾,头、尾中包含只有磁盘控制器能识别的扇区号码和纠错等信息,地址是磁道+盘面+扇区
扇区编号
扇区编号,按照(C,H,S)将扇区形成一 维扇区数组,数组索引就是扇区编号
某扇区(c,h,s)编号A = c*H*S + h*S + s
扇区总数 = C*H*S
CHS模式
以前,硬盘的容量还非常小,采用与软盘类似的结构生产硬盘:也就是硬盘盘片的每一条磁道都具有相同的扇区数,由此产生了3D参数:磁柱面数(Cylinders) 头数(Heads) 扇区数(Sectors per track)
CHS(Cylinder/Head/Sector)模式下磁盘的大小:
- 磁头数(Heads) 表示硬盘总共有几个磁头,也就是有几面盘片, 最大为 256 (用 8个二进制位存储);
- 柱面数(Cylinders) 表示硬盘每一面盘片上有几条磁道, 最大为 1024(用 10 个二进制位存储);
- 扇区数(Sectors per track) 表示每一条磁道上有几个扇区, 最大为63 (用 6 个二进制位存储)。
每个扇区一般是 512个字节; 所以磁盘最大容量为:256 * 1024 * 63 * 512 / 1048576 = 8064 M
- CHS(Cylinder/Head/Sector)模式,这种方式会浪费很多磁盘空间 (与软盘一 样)
- 为了进一步提高硬盘容量,产生了等密度结构硬盘,外圈磁道的扇区比内 圈磁道多,采用这种结构后,硬盘不再具有实际的3D参数,寻址方式也改 为线性寻址,即以扇区为单位进行寻址。
- 为了与使用CHS寻址的兼容 (如使用BIOS Int13H接口的软件),在硬盘控制 器内部安装了一个地址翻译器,由它负责将老式3D参数翻译成新的线性参数。
磁盘速度和内存速度差异
- 磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字 节,磁盘也会从这个位置开始,顺序向后读取一定扇区长度的数据放入 内存。
- 这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被 用到时,其附近的数据也通常会马上被使用。
进程IO过程
- 得到要访问的扇区编号;得到读盘的目标(或写盘的源)内存地址
- 将扇区编号和内存地址写给DMA;然后阻塞进程
- DMA处理完成后中断CPU;中断处理程序唤醒阻塞进程
- 进程继续
硬盘布局
- 物理盘以扇区(一般为512字节)为单位进行 编址,它是硬盘读写的基本单位
- 一块硬盘从逻辑上可以理解为连续的一维扇区序列
- 整个硬盘的第1个扇区存储着“主引导记 录(MBR)” :
- 引导可执行代码;
- 硬盘基本分区 表最多包含4个基本分区位置信息
- 除了第1个扇区之外,其余扇区可以划分 为至多4个基本分区,每个分区的第1个扇区预留,可以作为引导扇区
- 每个分区除第1个扇区外的其他部分还可以看做一个硬盘,继续分区,这样的分区可以无限制地重复进行,直 到硬盘划分完成为止
一些概念
- 扇区 - 物理盘存储空间基本编址单位,一般为512字节
- 主引导记录MBR - 硬盘的第1个扇区的内容,含引导代码和主分区表
- 分区 - 硬盘中可以作为逻辑盘管理的一组扇区集合
- 可扩展分区 - 可以继续划分成“分区”的硬盘分区
- 引导分区 - 标记有可引导标记的硬盘分区,这种分区有引导扇区和引导文件
- 引导扇区 - 引导分区的第1个扇区
- 可扩展分区引导记录 - 可扩展分区中第2个扇区中的内容
交换分区
在请求调页时如果发生页面置换,交换出去的页面要写到磁盘上的生磁盘(raw disk),为提高效率,这部分磁盘不存文件,直接用扇区号寻址
Linux交换分区
- 安装Linux时,需创建一硬盘分区作为交换分区,可以通过fdisk查看分区信息
- 因为交换分区要和内存不断交换,所以是动态变化的,swap分区的大小通常是内存大小的两倍
固态盘
由NAND FLASH作为存储介质,由一个嵌入式控制器控制NAND FLASH 的操作,RAM作为buffer,通过IDE, SATA, PCI-e等总线对外提供块接口。
SSD性能特性
-
顺序访问比随机访问快
- 典型存储器层次结构问题
-
随机写较慢
- 擦除块需要较长的时间(~1ms)
- 修改一页需要将块中所有页复制到新的块中
- 早期SSD 读/写速度之间的差距更大
SSD vs 机械磁盘
- 优点:
- 没有移动部件 更快、能耗更低、更结实
- 缺点:会磨损
- 闪存翻译层中的平均磨损逻辑试图通过将擦除平均分布在所有块上来最大化每个块的寿命
SSD软件结构
FTL(Flash Translation Layer)
- SSD是以硬盘的替代者的姿态出现,为了与现有系统无缝对接,SSD必须 对外提供的是块接口,作为主机端,所看到的SSD是一个和HDD一样的块 设备。
- 为了达到模拟块设备的目的,SSD中需要FTL作为中间层
- FTL从主机文件系统接收块级请求(LSN, size),经过FTL的处理,产生 flash的各种控制命令
FTL由三部分组成:
- Address mapping (地址映射)
- 上层文件系统发送给SSD的任何读写命令包括两个部分(LSN,size)
- LSN是逻辑扇区号,对于文件系统而言,它所看到的存储空间是一个线性 的连续空间。例如,读请求(260,6)表示的是需要读取从扇区号为260 的逻辑扇区开始,总共6个扇区。
- 请求到达SSD后,需要经过地址转换,将逻辑扇区转换成NAND FLASH中 的物理页号
- 损耗平衡(Wear-Leveling)
- Flash中每个块都有一定的擦写次数限制。故不能让某一个块被写次数较 多,而其他块被写的次数较少
- 需要找一种方法:使flash中每个块被擦写的次数基本相同
- 动态损耗平衡
- 在请求到达时,选取擦除次数较少的块作为请求的物理地址。
- 静态损耗平衡
- 在运行一段时间后,有些块存放的数据一直没有更新(冷数据),而有 些块的数据经常性的更新(热数据)。那些存放冷数据的块的擦除次数 远小于存放热数据的块。将冷数据从原块取出,存放在擦除次数过多的 块,原来存放冷数据的块被释放出来,接受热数据的擦写。
- 动态损耗平衡
- 垃圾回收
- SSD在使用过程中,会产生大量失效页,在SSD的容量到达一定阈值时,需 要调用GC函数,清除所有失效页,以增加可用空间。