0 缘起为什么想要分享I/O先说为什么想要分享一下磁盘I/O相关的内容。我们都知道,计算机是由CPU、内存和各种I/O设备组成的,其中CPU和内存的运行速度是很快的,纳秒级和微秒级,I/O设备的运行速度是很慢的,是毫秒级的。如果程序逻辑设计的有些冗余,只会对CPU、内存产生一些浪费,但是由于他们的运行速度很快,通常不会构成系统性能的瓶颈,但是I/O不一样,它本身速度很慢,如果设计的不好,就会容易导致系统性能产生瓶颈,因此,I/O相当于木桶理论中最短的板,水桶能装多少水(性能达到多少),往往由I/O设计的好坏决定,既然I/O如此重要,希望将它总结分享出来。
本文主旨脉络本文会分成三大part进行介绍,第一part会介绍磁盘相关的内容,磁盘是数据存储的基础,它提供了基于扇区的数据读写能力,如果没有磁盘,就谈不上文件系统,更谈不上I/O了,所以,磁盘是数据组织和管理的物理基础。但是光有磁盘是无法完成数据的组织和管理的,因为,用户对数据使用的最小颗粒度是文件,而文件除了能够存储数据,还能提供更加复杂的功能,比如按照目录结构的数据组织方式、文件的权限控制、硬链接、软链接等,为了支持这些复杂的文件管理功能,就需要有文件系统,因此,什么是文件系统呢?文件系统是基于磁盘基础之上,为数据的访问和管理提供更加复杂功能的一个产物,这是对一个对文件系统定性的理解方式。有了文件系统,我们就可以开始对数据进行访问了,访问的过程中,需要CPU、内存等其他硬件的共同支持和配合,完成一次数据访问的过程,就叫做一次I/O。综上,磁盘是数据存取的物理基础,文件系统是基于磁盘提供文件组织管理功能,I/O是结合其他硬件完成一次文件访问的整个过程,这就是对磁盘、文件系统、I/O的定性理解。本文接下来也会按照这个思路进行内容组织。
1 磁盘物理结构和运行原理
1.1 磁盘的物理结构磁盘的物理结构如下图所示:
1-1 磁盘的物理结构
一个磁盘有多个盘面组成,一个盘面的上下两个面都是可以进行数据读写的,每个面都有一个读写磁头(Head),每个盘面是由很多半径不同的同心圆组成的,每个同心圆是一个磁道(Track),不同盘面的同一磁道组成一个柱面(Cylinder),每个磁道又可以划分为多个扇区(Sector),每个扇区能存储512字节数据,因此,磁盘容量 = C * H * S * 512 byte。
磁盘的最小单位是扇区,计算磁盘的容量等价于计算磁盘中扇区的数量。
仔细分析一下,其实柱面的数量和磁道的数量是相等的,为什么磁盘容量的计算没有用磁道数,而是用柱面数?很多资料上没有说明这个原因,但我的理解是:这跟磁盘的读写顺序是有关的,磁盘是以柱面为单位进行数据读写的(后面会详细说明)。
1.2 磁盘的运行原理
由于每个盘面上都有磁头,当磁盘高速旋转的时候,会与盘面保持一个很小的距离,磁头就可以进行数据读取,这就是磁盘运行的基本原理。
给定任意一个扇区,如果想要读取该扇区的数据,需要三个步骤:a. 寻道:通过移动磁头,找到数据所在的磁道(柱面),这个过程叫寻道延迟,大概会消耗3~15ms;b. 旋转:通过旋转定位到磁头上具体的扇区,这个过程叫旋转延迟,大概会消耗2~4ms;c. 读写数据:这个过程速度很快,可以忽略不计;
因此,读写一个扇区的数据需要大约10ms左右。磁盘上的任意扇区都可以通过(磁头号,磁道号,扇区号)的三元组唯一标识,这个三元组就是磁盘的物理地址,磁头是从0开始编号,如果有M个磁头,则磁头编号是0 ~ M-1,磁道也是从0开始编号,如果有N个磁道,则磁道编号从0 ~ N-1,扇区与前两者不同,扇区是从1开始编号,如果有Q个扇区,则扇区编号从1 ~ Q,为什么唯独扇区是从1开始编号,不得而知,猜测是因为命名习惯吧。
从上述过程中,我们可以分析出两个结论:1、做数据读写的时候,寻道和旋转是最耗时的,因为他们都是机械运动,而数据读取的速度很快,为了充分利用这次寻找扇区所花费的时间,我们可以多读取一些数据,比如4KB,这样并不会增加一次数据读写的时间,反而提升了数据读写的效率;2、既然寻道和循转最耗时,在数据读写过程中,如果能减少这两种操作,就可以提升数据读写的效率。
1.3 磁盘的读写顺序你是否想过这个问题:当往磁盘中写入一个非常大的数据,数据大到会占据整个磁盘,这个时候磁盘是按照怎样的顺序来写数据的?先写哪个扇区?
在磁盘开始运转的时候,磁头默认是放到0号磁道的1号扇区的,这个初始状态是人为设定的,所以,磁盘是以这个位置为起点开始写入数据,为了弄懂接下来的逻辑,需要把时间放慢很多倍,想象:当写完0号磁头0号磁道的1号扇区时,由于读写数据的速度非常快,磁盘才旋转了一点点,还要等很久磁盘才能旋转到0号磁头0号磁道的2号扇区,磁盘会这样一直等下去?当然不会,磁盘会把磁头切换到1号,然后把数据写入1号磁头0号磁道1号扇区,写完之后还没旋转到2号扇区,因此,继续写2号磁头0号磁道1号扇区,直到把所有磁头的0号磁道1号扇区的数据都写完,这些数据从上到下连成一条线。
接下来等到磁盘旋转到2号扇区的位置,再开始写0号磁头0号磁道2号扇区,1号磁头0号磁道2号扇区,就这样又写完一条线,循环下去数据就写满了第0号柱面,接下来,机械臂控制磁头往圆心方向移动到1号磁道,按照上述的方式,1号柱面的数据也被写满,最终,所有柱面的数据都被写满。总的来讲,数据写入的顺序是:以柱面为单位,从上到下,从外到内。具体过程可以参考下图:
1-2 磁盘读写扇区顺序
1.4 磁盘的抽象磁盘的每个扇区都有一个唯一的物理地址,即(磁头号,磁道号,扇区号)的三元组,假设磁头的数量是M,每个盘上磁道的数量是N,每个磁道上扇区的数量是Q,则一共有MNQ个扇区,再通过一个简单的数学变换就可以把磁盘的物理地址空间转换为线性地址空间,线性地址的范围是0 ~ MNQ-1,具体的转换过程如下:
1-3 物理地址到逻辑地址的映射
以一个80个磁道(柱面),18个扇区,2个磁头(1张磁盘)的磁盘为例,以柱面为单位,对扇区进行编号,扇区的编号从1~2880,即,可以将磁盘抽象成数组。这个抽象非常重要,文件系统的设计都是以数组模型为基础的。
1.5 小结
磁盘提供了基于扇区进行数据读写的基本能力:就是在扇区上读写数据,这是构建文件系统的基础,文件除了可以存储数据,还有文件名,文件的访问权限控制等功能,这些功能需要交给文件系统来完成。虽然磁盘是圆柱形的结构,但它本质上是对连续的扇区进行读写操作,每个操作单元是512个字节,这跟数组的结构很像,因此,我们可以将磁盘抽象为数组,每个元素可以存储512个字节(一个扇区大小),因此,文件系统的构建就从数组模型作为起始点。