机械硬盘( HDD , Hard Disk Drive )主要由盘片、磁头、电机马达、接口等组成。
一个 机械硬盘 由多个 盘片 叠加而成。

盘片( Platters )的表面涂有 磁性物质 ,这些磁性物质用来记录二进制数据。工作时在主轴马达的带动下进行高速旋转(比如 每分钟 7200 转 )。每个盘片都有上下两面,称为盘面,每个盘面都有一个对应的读写磁头负责读写该盘面上的数据。
当关机时,磁头会停留在硬盘的 停泊区 ,工作时才会移动到盘面上方,依靠磁盘高速旋转引起的空气动力效应悬浮在盘面上。
在硬盘系统中,盘面按照从上到下的顺序从 0 开始编号,盘面号也叫磁头号,比如一个硬盘有 两个盘片 ,则盘面号为 0 ~ 3 。
名词解释:
在盘片高速旋转时保持磁头不动,那么磁头就会在盘面上形成一个圆形的轨迹,这些同心的圆形轨迹就是 磁道 ( Track )。每个盘面上都有多个磁道,这些磁道 由外向内 从 0 开始顺序编号。
所有盘面上半径相同的同心磁道垂直堆叠在一起构成的一个圆柱,称为 柱面 ( Cylinder )。柱面是一个抽象出来的概念,它在物理上不是一体的,只是在空间上类似于一个圆柱的外壁。 为了方便理解,可以认为柱面就是磁道 。柱面上的磁头 由上到下 从 0 开始顺序编号,数据的读写也是按照柱面进行。
在读写数据时,首先在同一柱面内从 0 号磁头开始操作,依次向下在同一柱面的不同盘面即磁头上进行操作,只有当同一柱面的所有磁头全部读写完毕后才将磁头切换到 下一个柱面 ( 同心圆往里的柱面 )。 这么做的原因是选取磁头只需通过电子切换即可,而选取柱面则必须通过机械切换,电子切换是相当快的,而机械切换磁头则要慢得多 。
概括来说,就是 当一个磁道写满数据后,就在同一柱面的下一个盘面上写,一个柱面写满后,才会移动到下一个柱面 ,读数据也是按照同样的方式。
盘面上可以划分出很多磁道,但是我们并不需要每次都读写这么多数据,所以又将磁道划分为了若干更小的弧段,每段被称为一个 扇区 ( Sector )。
由于这些弧段转动的 角速度一样 ,但是长度不同,所以 线速度也不一样 ,外圈的线速度大于内圈,即 相同的转速下,在同样的时间段内外圈划过的弧段长度要比内圈划过的弧段长度大 。
扇区从 1 开始编号,是硬盘进行读写操作的最小单位 ,一般硬盘的一个扇区大小为 512 字节 ——这也就意味着哪怕我们只存放 1 字节的数据也会占用硬盘的一个扇区(512 字节)。后来为了提升硬盘的效率和使用率又推出了 4K 大小的扇区 标准。
扇区存储的第一个主要部分 就是标识符,也就是扇区头标,它是一个扇区的三维地址,包括盘面号、柱面号和扇区号,通过这三个地址可以唯一确定一个扇区。可用( 柱面号 , 盘面号 , 扇区号 )来定位任意一个 “磁盘块”。
在 文件的物理结构中,我们经常提到文件数据存放在外存中的几号块(逻辑地址),这个块号就可以转换成( 柱面号 , 盘面号 , 扇区号 )的地址形式。
可根据该地址读取一个 “块”,操作如下:

扇区的第二个主要部分 就是存储数据的数据段,可分为数据和保护数据的纠错码( ECC )。
存储容量 = 磁头数(盘面数)* 磁道数(柱面数)* 每个磁道的扇区数 * 每个扇区的字节数
从硬盘的物理结构来看,数据存取信息的最小单位是扇区,一个扇区可能为 512 字节 或者是 4K 。
由于扇区的容量小且数量众多,在寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个整体, 这个整体就是操作系统对硬盘进行存取的最小单位 ,在 Windows 下称为 簇 ( Cluster ),在 Linux 等系统中称为 块 ( Block )。每个簇或块可以包含 2, 4, 8, 16, 32 等, 2 的 n 次方个扇区 。
Windows 系统上通过管理员身份运行 fsutil fsInfo ntfsInfo C: 命令,会得到以下信息:
这台设备使用的文件系统是 NTFS ,默认的簇大小为 4096 字节 。
Linux 系统上通过以下命令可以查看 block 信息:
设置 cmd 的显示语言
当需要从硬盘读取数据时,操作系统会将数据的逻辑地址发送给硬盘,硬盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即确定要读取的数据在哪个磁道,哪个扇区。
为了读取这个扇区的数据,需要将磁头移动到这个扇区的上方,为了实现这一点:
可以看到,进行一次读写硬盘所需要的时间可以概括为: 寻道时间 、 旋转时间 和 传输时间 。目前硬盘的平均寻道时间在 3ms 到 15ms 之间,普通硬盘的转速一般为 5400 rpm 或 7200 rpm 。
由于存储介质的特性,硬盘本身的存取速度就比主存慢很多,再加上磁头的机械运动,存取速度就更慢了。
为了提高硬盘的效率, 尽量减少磁盘 I/O ,硬盘往往不是严格的按需存取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序地向后读取一定长度的数据放入内存,这样做的理论依据是计算机科学中著名的 空间局部性原理 :

程序在运行期间,一段时间内所需要的数据通常都比较集中,由于磁盘的顺序读取效率很高(不需要寻道时间,只需要很少的旋转时间),因此 预读一般都可以提高磁盘 I/O 的效率 。
磁盘预读的长度一般为 页 ( Page )的整数倍。由于操作系统经常与内存和硬盘这两种设备进行通信,为了屏蔽底层物理存储结构的设计细节,需要抽象出一种逻辑上的存储单位。
当程序要读取的数据不在内存中时,会触发一个缺页异常,此时操作系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置然后连续读取一页或者几页的数据放入内存,然后异常返回,程序继续执行。
硬盘 按 数据接口 不同,大致分为 ATA 和 SATA (可参阅 IDE 界面)以及 SCSI 和 SAS 。


