一直以来,个人对于磁盘的底层技术很少关注,可能更多的是关注磁盘IO性能,读写速率,这篇博文就磁盘扇区(Sector)和块/簇这方面的知识做一些深入性的总结,希望对你有所帮助!如有不足或错误的地方,也敬请指正!
扇区(Sector)的概念
什么是扇区(Sector)呢?我们先看看维基百科关于扇区的定义:
In computer disk storage, a sector is a subdivision of a track on a magnetic disk or optical disc. Each sector stores a fixed amount of user-accessible data, traditionally 512 bytes for hard disk drives (HDDs) and 2048 bytes for CD-ROMs and DVD-ROMs. Newer HDDs use 4096-byte (4 KiB) sectors, which are known as the Advanced Format (AF).
The sector is the minimum storage unit of a hard drive.[1] Most disk partitioning schemes are designed to have files occupy an integral number of sectors regardless of the file's actual size. Files that do not fill a whole sector will have the remainder of their last sector filled with zeroes. In practice, operating systems typically operate on blocks of data, which may span multiple sectors.[2]
Geometrically, the word sector means a portion of a disk between a center, two radii and a corresponding arc (see Figure 1, item B), which is shaped like a slice of a pie. Thus, the disk sector (Figure 1, item C) refers to the intersection of a track and geometrical sector.
In modern disk drives, each physical sector is made up of two basic parts, the sector header area (typically called "ID") and the data area. The sector header contains information used by the drive and controller; this information includes sync bytes, address identification, flaw flag and error detection and correction information. The header may also include an alternate address to be used if the data area is undependable. The address identification is used to ensure that the mechanics of the drive have positioned the read/write head over the correct location. The data area contains the sync bytes, user data and an error-correcting code (ECC) that is used to check and possibly correct errors that may have been introduced into the data.
在计算机磁盘存储中,扇区是磁盘或光盘上磁道的细分。每个扇区存储固定数量的用户可访问数据,传统上,硬盘(HDD)上的扇区大小为512字节,CD-ROM和DVD-ROM的扇区大小为2048字节。较新的硬盘(HDD)使用4096字节(4 KiB)扇区,这些扇区称为高级格式(AF)。
扇区是硬盘的最小存储单元。[1]大多数磁盘分区方案旨在使文件占据整数个扇区,而不管文件的实际大小如何。未填充完整个扇区的文件将最后一个扇区的其余部分填充零。实际上,操作系统通常使用数据块操作,数据块可跨越多个扇区。[2]
从几何学上讲,“扇形”一词是指圆盘中心,两个半径和相应弧之间的一部分(请参见图1,B项 紫色部分),其形状像一块馅饼。因此,磁盘扇区(图1,C项 玫红色部分)是指磁道和几何扇区的交集。
在现代磁盘驱动器中,每个物理扇区都由两个基本部分组成,即扇区头区域(通常称为“ ID”)和数据区域。扇区头包含驱动器和控制器使用的信息。该信息包括同步字节,地址标识,缺陷标志以及错误检测和纠正信息。如果数据区域不可靠,则标头还可以包含要使用的备用地址。地址标识用于确保驱动器的机械手已将读/写头定位在正确的位置上。数据区域包含同步字节,用户数据和纠错码(ECC),用于检查并可能纠正可能已引入数据中的错误。
我们来看看下面维基百科上的图,形象的介绍了扇区、磁道等概念:
A:Track 磁盘磁道(粉红色部分)
B:Geometrical sector 几何学中的扇形(紫色部分)
C:Track sector 磁盘扇区(玫红色部分)
D:Cluster 块/簇(绿色部分)
图(1)
说完扇区,就不得不提一些其他相关概念,因为它们相辅相成,不能孤立开来,这里也简单介绍一下,不详细展开.
磁头(head)
磁头就是读写盘片的设备。如下所示
盘片(platter)
硬盘中一般会有多个盘片组成,这个如果拆解过磁盘的人都会知道,银白色的盘片像镜子一样,曾有同事将其当镜子用。大多数盘片的材质是铝合金,上面覆盖一些磁性涂层。IBM曾经生产过玻璃材质的盘片,不过早已退出了历史舞台。每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制,盘片数量都受到限制,一般都在5片以内。盘片的编号自下向上从0开始,如最下边的盘片有0面和1面,再上一个盘片就编号为2面和3面。
柱面(cylinder)
硬盘通常由重叠的一组盘片构成,每个盘面都被划分为数目相等的磁道,并从外缘的“0”开始编号,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面。磁盘的柱面数与一个盘面上的磁道数是相等的。由于每个盘面都有自己的磁头,因此,盘面数等于总的磁头数。
所有盘面上的同一磁道构成一个圆柱,称作柱面。数据的读/写按柱面从外向内进行,而不是按盘面进行。定位时,首先确定柱面,再确定盘面,然后确定扇区。之后所有磁头一起定位到指定柱面,再旋转盘面使指定扇区位于磁头之下。写数据时,当前柱面的当前磁道写满后,开始在当前柱面的下一个磁道写入,只有当前柱面全部写满后,才将磁头移动到下一个柱面。在对硬盘分区时,各个分区也是以柱面为单位划分的,即从什么柱面到什么柱面;不存在一个柱面同属于多个分区
了解完上面概念,你再看一下下面两张图【来自维基百科】,基本上就能有个形象的认知了。
物理扇区(physical sector)与逻辑扇区(logical sector)
关于物理扇区(physical setctor)与逻辑扇区,这个还得扯上扇区大小,由于近年来,随着对硬盘容量的要求不断增加,为了提高数据记录密度,硬盘厂商往往采用增大扇区大小的方法,于是出现了扇区大小为4096字节的硬盘。我们将这样的扇区称之为“物理扇区”。但是这样的大扇区会有兼容性问题,有的系统或软件无法适应。为了解决这个问题,硬盘内部将物理扇区在逻辑上划分为多个扇区片段并将其作为普通的扇区(一般为512字节大小)报告给操作系统及应用软件。这样的扇区片段我们称之为“逻辑扇区”。实际读写时由硬盘内的程序(固件)负责在逻辑扇区与物理扇区之间进行转换,上层程序“感觉”不到物理扇区的存在。
逻辑扇区是硬盘可以接受读写指令的最小操作单元,是操作系统及应用程序可以访问的扇区,多数情况下其大小为512字节。我们通常所说的扇区一般就是指的逻辑扇区。物理扇区是硬盘底层硬件意义上的扇区,是实际执行读写操作的最小单元。是只能由硬盘直接访问的扇区,操作系统及应用程序一般无法直接访问物理扇区。一个物理扇区可以包含一个或多个逻辑扇区(比如多数硬盘的物理扇区包含了8个逻辑扇区)。当要读写某个逻辑扇区时,硬盘底层在实际操作时都会读写逻辑扇区所在的整个物理扇区。
关于扇区的一些疑问
回过头来,我们仔细捋一捋图(1)这张图片,基本上就能把扇区的概念理解得七七八八了,那么还有几个问题,这个是我学习过程的一些疑问和自我解答(这里仅仅指传统硬盘,不涉及SSD磁盘):
1:扇区的大小是固定的吗? 同一块磁盘上的扇区大小是否可以不一致。
扇区(Sector)大小是固定的,默认情况下,每个扇区(Sector)为512字节,2009年后,硬盘厂商开始发布4KB字节扇区的硬盘了,4KB扇区硬盘已经在消费级市场广泛应用。但是同一块硬盘上的扇区大小一定是一致的。不可能存在多种不同大小的扇区。
至于为什么之前的扇区大小为512字节呢?这是1956年由industry trade organization, International Disk Drive Equipment和Materials Association三家机构确定的行业标准。有时代和技术的限制,因为磁盘技术发展初期,存储容量非常小。512字节的扇区也够用,但是随着时代的发展,512字节大小的扇区(Sector)明显太小了,由于每个扇区(Sector)还要存放很多其他信息,因此增大sector size可以降低扇区(Sector)的数量,从而提高实际存储量,同时降低了差错校验等很多CPU计算量。但遗憾的是由于这个标准太根深蒂固,要想改变一些底层代码或架构势必非常困难,所以现在4KB扇区硬盘暂时还没有全部普及。
至于为什么要采用4KB扇区的硬盘呢?这是因为它可以提高可靠性且增加磁盘容量 — 至少从理论上讲是这样。 更多相关详细资料,建议参阅下面资料:
https://www.ituring.com.cn/article/22103
https://www.ibm.com/developerworks/cn/linux/l-4kb-sector-disks/index.html
https://www.ibm.com/developerworks/cn/linux/l-linux-on-4kb-sector-disks/index.html
2:每个磁道(Track)上的扇区数量都是一样的吗? 还是只是相同柱面(cylinder)上的扇区数量一致。
要回答这个问题,我们首先有必要了解一下CLV、CAV、ZBR等技术,当然这里仅仅是入门介绍,更多相关知识(例如P-CAV、Z-CLV等技术),自行去搜索查阅。
CLV技术
一开始的技术叫做CLV,称为恒定线速度,这个技术要求无论在哪个圈上,线速度都要一样,所以对马达的要求非常高,寿命非常短,在低于12倍速的光驱中使用的技术。光碟片和硬碟不同,光碟片上每个部分的密度都是一样的,在同样旋转一圈的情况下,圆周较长的外圈部分在读取资料时会比内圈部分快,所谓的恒定线速度是指从内到外都是同样的读取速度,而为了保持一开始速度,读到外圈时会降低光碟片的转速来配合读取速度,读到内圈时会提高转速。
CAV技术
CLV因为不停的更改马达的转速,会对机器的寿命造成一定的影响,而且磁盘转速也不能无限制的加快。后来又有了一种磁盘技术叫做CAV,叫做恒定角速度,马达的转速恒定,寿命有了很大提高,光盘上的内沿数据比外沿数据传输速度要低,越往外越能体现光驱的速度,倍速指的是最高数据传输率。但是也有缺点,浪费会很大,因为磁头读盘片的扫描频率基本是恒定的,外圈的有效磁介质单元会很稀疏。这时候,各个磁道的扇区数应该是一样的。
ZBR技术
在计算机存储中,区域位记录(ZBR)是磁盘驱动器用来优化磁道以增加数据容量的一种方法。它通过在外部磁道上每个区域放置比内部磁道更多的扇区来实现此目的。这与其他方法相反,例如恒定角速度(CAV)驱动器,其中每个磁道的扇区数相同。在由大致同心的轨道组成的磁盘上(无论是实现为单独的圆形轨道还是实现为单个螺旋轨道),物理轨道的长度(周长)随着距中心轮毂的距离增加而增加。
如下图片所示,可以看到粉红色、绿色、灰色部分的扇区数量不一样。
ZBR区位记录,也称为zone-bit recording,zone recording,zone-density recording或者multiple-zone recording,是指为了提高磁盘的存储容量,充分利用磁盘外面磁道的存储能力,现代磁盘不再把内外磁道划分为相同数目的扇区。
所有的硬盘驱动器都是由一些磁盘片组成。在每个磁盘片中,数据存放的物理位置呈同心圆状,这些同心圆称为磁道。每个磁道上包含若干扇区。每个扇区存储的数据容量是一致的。磁道的周长与同心圆的直径成正比。在早期的硬盘驱动器中,所有的磁道包含的扇区数目都是一样的,按照固定的圆心角辐射出去,就可以简单的将各磁道的扇区数进行统一。这样,在磁道边缘的扇区弧长就要大于内部的扇区弧长,其存储数据的密度也要比内部磁道的密度要小。最终,导致外部磁道的空间浪费。为了有效利用外部磁道空间,让所有的磁道扇区存储数据密度一致,就需要保证所有扇区的弧长一致。这样就要根据磁道的半径来重新分配扇区数目。Zoned0bit recording 方法通过将磁道分组(这种磁道组称为zone)实现了这一目标。内部磁道的扇区数目较少,外部磁道的扇区数目较多。这样,外部磁道和内部磁道的存储空间利用率都相等,充分利用了整个硬盘的空间。【来自百科】
ZDR(Zone Data Recording),即区域数据记录技术。主要工作方式还是CAV,但是采取了分区方式,是每个区域内为恒定角速度,各个区域内选取的角速度不一样。从磁盘的最外圈到内圈划分出若干个区域。每个区域内的每磁道扇区一致,但靠内的区域比外侧的区域的每磁道扇区数要少,从而可以根据不同的磁道长度来合理设定扇区的数量,以达到充分利用磁盘存储空间的目的。但设置多少个区域,每个区域的扇区数设定也都是有讲究的。否则会在向内跨区域读写时造成传输率下降过大而影响整体性能。大多数产品划分了16个区域,最外圈的每磁道扇区数正好是最内圈的一倍,与最大的持续传输率的参数基本成比例。比如0到100磁道采用每小时120码的速度,101到200磁道采用每小时100码的速度,201到300采用每小时80码的速度。
所以要回答这个问题,要根据磁盘的数据记录方式:
1.旧式——非ZBR区位记录(不同磁道扇区数相同)
所有磁道(Track)上的扇区数量一致。以前的硬盘技术(CAV),内圈外圈每个磁道的扇区数是相同的,所以速度都是一样的。旧的磁盘驱动器中,外轨道和内轨道具有相同的扇区数,因此外磁道数据密度低。这是低效率的对可用空间的利用
2.新式——ZBR区位记录(不同磁道扇区数不同)
不同磁道(Track)上的扇区数量不一致,离圆心越远的磁道的扇区数量越多(外层环带的磁道拥有较内层环带的磁道更多的扇区)。
3:扇区在磁道上的面积大小是固定吗?
对于旧式磁盘(非ZBR区位记录)。如上,图(1)所示,扇区在不同的磁道,扇区的面积大小不一样。这个图只是为了形象的说明扇区的逻辑概念,实际情况呢? 准确答案是:扇区的大小在不同的磁道确实不一样。因为所有的磁道(Track)的扇区数量是一样的,那么离圆心越远的磁道的面积就越大,如果全部扇区的大小都一样的话,那么离圆心越远的磁道(Track)的扇区数量就应该越多,显然不是这样的。硬盘的每个磁道具有相同数量的扇区,并且扇区大小一致。这意味着,内部磁道中的位密度远高于外部扇区中的位密度。也就是说不同磁道的位密度(bit density)有差别。
显然,对于新式磁盘(ZBR区位记录),所有的磁道扇区存储数据密度一致,所有扇区的弧长一致。
4:磁盘介质中存储的密度是否不一样?
其实问题3已经顺带回答了。
我们再来聊聊块(Block)/簇(cluster)跟扇区(sector)的关系吧,关于扇区,经过上面的介绍,相信我们已经全面了解了扇区的基本概念。其实磁盘读写的基本单位是扇区,而块(Block)/簇(cluster)是一个逻辑概念,或者说是操作系统中的概念,其实对于实际物理磁盘,并没有所谓的块(Block)这样的东东。操作系统为什么要虚拟个这样的概念出来呢?这样又有什么好处呢?相信你也有不少这类疑问!
块/簇
块(Block)/簇(Cluster)是逻辑上的概念,或者说是虚拟出来的概念。 分别对应Linux与Windows操作系统中的概念。注意:有些文章或资料叫做磁盘块/磁盘簇。这里统一用块(Block)/簇称呼,这篇文章你看到的块(Block)指磁盘块。后面不再做声明。
Unix与Linux系统中,块(Block)是操作系统中最小的逻辑存储单位。操作系统与磁盘打交道的最小单位是块(Block)。
在Windows下如NTFS等文件系统中叫做簇;
每个簇或者块可以包括2、4、8、16、32、64…2的n次方个扇区
如下所示,Windows下E盘的Cluster的大小为4Kb大小,如下所示:
Linux下查看Block大小的语句如下:
# stat /home | grep "IO Block"
Size: 47 Blocks: 0 IO Block: 4096 directory
# tune2fs -l /dev/mapper/VolGroup03-LogVol00 | grep Block
Block count: 47177728
Block size: 4096
Blocks per group: 32768
#dumpe2fs /dev/sda1|grep -i "block size"
为什么要用磁盘块/簇?
我们知道磁盘的最小单位就是扇区,那么为什么操作系统不用扇区作为IO的基本单位呢? 为什么操作系统一定要整出块(Block)/簇(Cluster)这样的概念呢?主要是因为下面两个原因:
读取方便:由于扇区的Size比较小,数目众多时寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个块,再对块进行整体的操作。
分离对底层的依赖:操作系统忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位。
其实我们生活中也有类似的例子,例如我们生活中,现在见到最小币值是角了,小时候的一分钱、两分钱现在已经很难见到了,因为随着经济发展和生活水平提高,如果还有分或角的话,非常不方便,你能想象你用一大袋币值
为1分的钱去买个几千块的商品吗? 想想都觉得这画面很滑稽。既不方便携带,也不方便计算。而且扇区是对硬盘而言,块是对文件系统而言。出于不同的需要。
块/簇是越大越好吗?
Linux系统
块(Block),也称为逻辑块,是文件系统层面的概念。文件系统不是一个扇区一个扇区的来读数据,太慢了,另外由于扇区的Size比较小,数目众多时寻址时比较困难。所以它是一个块一个块的读取数据,就是说块(Block)是文件系统存取数据的最小单位,一般大小是4KB(这个值可以修改,在格式化分区的时候修改)。
读取一个块,实际上是从硬件设备读取一个或多个扇区,一个块只能存放一个文件的内容,无论这个文件有多小。一个文件可能会占用一个或多个Block,每读取一个block就会消耗一次磁盘IO。如果要提升磁盘IO性能,那么尽可能一次IO读取更多的数据,但是Block也不是越大越好,需要结合业务来设置。
试想,如果块的大小为8KB,但是很多小文件都是1KB大小,我们知道一个块只能存放一个文件的内容,那么就会造成很大的浪费。
Windows系统
磁盘簇:扇区是磁盘最小的物理存储单元,但由于操作系统无法对数目众多的扇区进行寻址,所以操作系统就将相邻的扇区组合在一起,形成一个簇,然后再对簇进行管理。每个簇可以包括2、4、8、16、32或64个扇区。显然,簇是操作系统所使用的逻辑概念,而非磁盘的物理特性。为了更好地管理磁盘空间和更高效地从硬盘读取数据,操作系统规定一个簇中只能放置一个文件的内容,因此文件所占用的空间,只能是簇的整数倍;而如果文件实际大小小于一簇,它也要占一簇的空间。所以,一般情况下文件所占空间要略大于文件的实际大小,只有在少数情况下,即文件的实际大小恰好是簇的整数倍时,文件的实际大小才会与所占空间完全一致
这种以簇为最小分配单位的机制,使硬盘对数据的管理变得相对容易,但也造成了磁盘空间的浪费,尤其是小文件数目较多的情况下,一个上千兆的大硬盘,其浪费的磁盘空间可达上百兆字节。
所以块/簇的大小不是越大越好,而是对读写性能与节省空间的多方权衡考虑。块和簇的大小都是可以调整的。Windows在格式磁盘时,可以通过"Allocation unit size"来调整簇的大小。如下所示,
如果我选择"Allocation unit size"为8192, 也就是簇大小为8KB重新格式化,那么你会看到”Bytes Per Cluster"值为8192了。
当然, Linux也可以在格式化时调整。如下所示:
#mkfs.ext4 -b 4096 /dev/sda
磁盘块大小必须是扇区大小的整数倍呢?
磁盘读取数据的基本单位就是一个扇区的大小,一个块的大小对于磁盘来说就是一次获取数据读取的扇区数*扇区大小,如果是整数倍的扇区数对于磁盘的IO更好,速度更快,也会更合理的利用资源。否则会对扇区进行分割。
一个扇区是512字节。有些硬盘厂商会提供4k大小扇区。这是物理结构。磁盘定下来的结构就是没法修改的。所以必须要将块设置为磁盘的大小。
如何映射磁盘块?
磁盘控制器,其作用除了读取数据、控制磁头等作用外,还有的功能就是映射扇区和磁盘块的关系
如何查看磁盘的扇区大小呢?
在Linux系统下面,我们可以下面命令查看操作系统逻辑块与物理块的大小,如下所示:
You can display what physical/logical sector sizes your disk reports via the /sys pseudo filesystem, for instance:
# cat /sys/block/sda/queue/physical_block_size
4096
# cat /sys/block/sda/queue/logical_block_size
512
我们可以查看具体磁盘的扇区大小(物理扇区大小与逻辑扇区大小)
[root@KerryDB ~]# fdisk -l /dev/sda
Disk /dev/sda: 500.1 GB, 500107862016 bytes, 976773168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0x8de02bd4
Device Boot Start End Blocks Id System
/dev/sda1 * 63 208844 104391 83 Linux
Partition 1 does not start on physical sector boundary.
/dev/sda2 208896 2306047 1048576 83 Linux
/dev/sda3 2306048 976773119 487233536 8e Linux LVM
[root@mylnx11 ~]# fdisk -l /dev/sda
Disk /dev/sda: 64.4 GB, 64424509440 bytes, 125829120 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000b86b7
Device Boot Start End Blocks Id System
/dev/sda1 * 2048 2099199 1048576 83 Linux
/dev/sda2 2099200 125829119 61864960 8e Linux LVM
注意,一些老旧的操作系统,使用fdisk -l没有明确显示扇区大小的信息,如下所示:
# more /etc/issue
Oracle Linux Server release 5.7
# fdisk -l /dev/sdb
Disk /dev/sdb: 171.7 GB, 171798691840 bytes
255 heads, 63 sectors/track, 20886 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/sdb1 1 20886 167766763+ 83 Linux
但是其Units计算,暗示了扇区大小为512字节。对于Windows系统而言,可以使用命令fsutil fsinfo ntfsinfo查看,如下截图所示
查看块(Block)的大小。
# stat /home | grep "IO Block"
Size: 47 Blocks: 0 IO Block: 4096 directory
# tune2fs -l /dev/mapper/VolGroup03-LogVol00 | grep Block
Block count: 47177728
Block size: 4096
Blocks per group: 32768
磁盘一次物理IO是读取一个扇区还是多个扇区? 这个是和朋友讨论的时候,最纠结的一个问题,因为之前确实没有了解过。咨询了不少人,得到的答案是一次IO会读取一个或多个扇区。虽然磁盘最小操作单位是扇区,但是不代表一次只能读取一个扇区。当然对于写操作也是如此。
读/写IO,最为常见说法,读IO,就是发指令,从磁盘读取某段扇区的内容。指令一般是通知磁盘开始扇区位置,然后给出需要从这个初始扇区往后读取的连续扇区个数,同时给出动作是读,还是写。磁盘收到这条指令,就会按照指令的要求,读或者写数据。控制器发出的这种指令+数据,就是一次IO,读或者写。
有兴趣的话,可以了解一下Multiple sector I/O
来自:Managing RAID on Linux: Fast, Scalable, Reliable Data Storage
参考资料:
https://en.wikipedia.org/wiki/Disk_sector
https://en.wikipedia.org/wiki/Cylinder-head-sector
https://en.wikipedia.org/wiki/Zone_bit_recording
https://blog.csdn.net/badbad_boy/article/details/4313645
https://www.ibm.com/developerworks/cn/linux/l-4kb-sector-disks/index.html
https://www.ibm.com/developerworks/cn/linux/l-linux-on-4kb-sector-disks/index.html
https://blog.csdn.net/lyh__521/article/details/46795201
https://unix.stackexchange.com/questions/178899/optimizing-logical-sector-size-for-physical-sector-size-4096-hdd