磁盘I/O子系统
一、数据写入磁盘流程
当执行向磁盘写入数据操作的时候,会发生如下的一系列基本操作。假设文件数据存在于磁盘扇区上,并且已经被读入到页缓存中。
- 进程使用write()系统调用写入文件。
- 内核更新映射到文件的page cache。
- 内核线程pdflush负责把页缓存刷入到磁盘中。
- 文件系统层把各个块缓存放入一个bio结构,并且提交一个写入到块设备层的请求。
- 块设备层从上层获得请求,执行I/O elevator操作,把请求放入到I/O请求队列中。
- 磁盘驱动,例如SCSI或其它特定驱动将会负责写操作。
- 磁盘驱动固件执行硬件操作,例如寻址、旋转、数据传送到磁盘的扇区
二、物理磁盘结构
磁盘是计算机主要的存储设备,也是计算机的主要构成硬件,磁盘主要由盘片、磁头、磁道、扇区、柱面这几部分组成。
- 盘片 : 磁盘由多个盘片组成,数据存储在这些盘片上,通过盘片的转动来让磁头读取数据的。
- 磁头: 在需要读取数据的时候,磁头就会移到这个盘片上面读取数据,磁头和盘片之间的距离非常小,但不会接触到盘片。如果出现断电的情况,那么磁头就会从盘片上移开移回到原来的位置。
- 磁道: 每个盘片就像一个“目标靶盘”,从中心向外分布着一圈圈的圆环,这些圆环被称为磁道。磁道是数据存储的基本单位,每个磁道上可以存储大量的数据。
- 扇区: 磁道是由一个一个的小圆环组成,每一个圆圈又进行了一个更小的划分,被称为扇区,如下面所示,一个磁道由八个扇区组成,每个扇区存储512个字节数据。
- 柱面: 柱面是多个盘片的磁道在相同位置的集合,如下面的黄色部分,四个盘面都有这个黄色的磁道,这样黄色部分的四个磁道就形成了一个圆柱体状的柱面。
三、缓存与脏数据
现代处理器的访问速度已经远远超过了主存储器的访问速度,为了解决这个问题,在CPU和内存之间添加一个高速内存, 这个高速内存容量小,只用来存储CPU执行时常用的指令。既保证了硬件成本,又提高了CPU的访问速度。
高缓存命中率是提升性能的关键。 为了获得高缓存命中率, 使用”局部性引用“的技术。 这个技术基于如下的原则:
最近使用过的数据即将被使用的可能性很高(时间局部性, temporal locality)。
使用过数据的附近数据被使用的可能性很高(空间局部性, spatial locality)
Linux在很多组件中用到了这个原则,例如页缓存、文件对象缓存(i-node缓存、目录条 目缓存等等)、预读缓冲区等。如下图所示:
在进程从磁盘中读数据时,数据被复制到内存中。该进程和其它进程都可以在内存缓存中读 取同样的数据副本。当进程尝试改变数据,进程首先修改内存中的数据,这时候,磁盘和内 存中的数据就不一致了,内存中的数据就叫做脏缓冲(dirty buffer)。脏缓冲应该尽快同步到 磁盘上,否则,如果突然崩溃,内存中的数据会丢失。
同步脏缓冲的进程叫做flush,在Linux内核2.6中,pdflush内核线程负责把数据写入到磁盘 上。数据会定时刷新(kupdate),或者当内存中的脏缓冲到了阀值的比例的时候 (bdflush)。这个阀值在/proc/sys/vm/dirty_background_ratio
文件中。
参考:
I/O子系统与磁盘调度详解-CSDN博客
https://juejin.cn/post/6844903747189997581
https://zhuanlan.zhihu.com/p/25779982455