硬盘分区及Linux文件系统

1. 硬盘物理结构

硬盘物理上主要分为:

  1. 盘片
    1. 磁道
    2. 扇区
  2. 机械臂
  3. 磁头
  4. 主轴

磁道:

当硬盘盘片旋转时,磁头若固定在一个位置上,则磁头会在盘片表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道。以盘片中心为圆心,由此可以划分出很多磁道来, 这些磁道用肉眼是根本看不到的,因为它们仅 是盘面上以特殊方式磁化了的一些磁化区,硬盘上的信息便是沿着这样的轨道存放的,盘片上的磁道由外向内依次从“0”开始进行编号。

柱面:

由于硬盘可以由很多盘片组成,不同盘片的相同磁道就组成了柱面(cylinder),如第一个图片。

磁头:

假设有N个盘片组成的硬盘,那么有2N个盘面(一个盘片有2面),那么磁头也就有2N个,即每个盘面有一个磁头。

扇区:

早期的硬盘盘片的盘面以圆心开始向外放射状将磁道分割成等分的弧段,这些弧段便是硬盘的扇区。每个扇区一般规定大小为512byte,这里大家应该比较疑惑,外圈周长很明显比内圈要长,怎么可能每个扇区都是512byte?其实答案早期硬盘外圈存储比内圈存储密度低一些,所以外圈很长但是仍然只能存储512byte,因此如果我们知道了柱面数(磁道数) Cylinders、磁头数Heads、扇区数Sectors,基本上硬盘的容量我们能够计算出来 硬盘总容量= Cylinders * Heads * Sectors * 512byte。但是由于早期硬盘外圈密度低,导致盘片利用率不高,现在的硬盘盘片则采用内外存储密度一致的方式,每个磁道都划分成以512byte大小的弧段,这样也造成了内外磁道上扇区数量会不一样,外圈上的扇区数要多于内圈扇区数。

磁盘寻址方式:

硬盘存取、读取数据,首先要做的就是寻址,即定位到数据所在的物理地址,在硬盘上就要找到对应的柱面、磁头以及对应的扇区,那么怎么寻址呢?   有两种方式:CHS和LBA

2. 磁盘分区

一般使用硬盘,首先会对硬盘进行分区,然后对分区使用某个文件系统格式(NTFS、FAT、ext2/ext3/ext4)进行分区格式化,然后才能正常使用。

柱面是分区的最小单元,即分区是某个柱面号开始到某个柱面号结束的。

 如图,柱面1~200可以分为一个区,柱面201~500再划分为一个区,501~1000再划分为一个区,以此类推。柱面0没有在任何分区里面,为何?  

前面说到硬盘从外圈(柱面0)到内圈扇区是依次编号,看似各个扇区没有什么区别,但是这里硬盘的柱面0的第一个扇区(逻辑扇区0,CHS表示应该是0/0/1)却是最重要的,因为硬盘的第一个扇区记录了整个硬盘的重要信息,第一个扇区(512个字节)主要记录了两部分:

 (1)MBR(Master Boot Record):主引导程序就放在这里,主引导程序是引导操作系统的一个程序,但是这部分只占 446 字节

 (2)DPT(Disk Partition table):硬盘分区表也在这里,分区表就是用来记录硬盘的分区情况的,例如c盘是1~200柱面,d盘是201~500柱面,分区表总共只占64字节,可以看出,分区其实很简单,就是在这个表里面修改一下记录就重新分区了,但是由于只有64字节,而一条记录就要占用16字节,这个分区表最多只能记录4个分区信息,为了继续分出更多分区来,引入了扩展分区的概念,也就是说,在这4个分区中,可以使用其中一条记录来记录扩展分区的信息,然后在扩展分区中再继续划分逻辑分区,而逻辑分区的分区记录则记录在扩展分区的第一个扇区中,如此则可以像链表一样划分出很多分区来。但是请注意,一个分区表中可以有1~4条主分区,但是最多只能有1个扩展分区

   举例,主分区可以是P1:1~200,扩展分区P2: 201~1400,扩展分区开始的第一个扇区可以用来记录扩展分区中划分出来的逻辑分区。

3. 理解 Linux 的 inode / block / superblock

磁盘分区完毕后还需要进行格式化(format),之后操作系统才能够使用这个文件系统。 为什么需要进行『格式化』呢?

这是因为每种操作系统所设定的文件属性/权限并不相同, 为了存放这些文件所需的数据,因此就需要将分区进行格式化,以成为操作系统能够利用的『文件系统格式(filesystem)』。每种操作系统能够使用的文件系统并不相同。

传统的磁盘与文件系统应用中,一个分区就是只能够被格式化成为一个文件系统,所以可以说一个 filesystem 就是一个 partition。但是由于新技术的利用,例如常听到的 LVM 与软件磁盘阵列(software raid), 这些技术可以将一个分区格式化为多个文件系统(例如 LVM),也能够将多个分区合成一个文件系统(LVM, RAID)! 所以说,目前在格式化时已经不再说成针对partition来格式化了, 通常称呼一个可被挂载的数据为一个文件系统而不是一个分区。

文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到inode 中,至于实际数据则放置到 data block 区块中。另外,还有一个超级区块 (superblock) 会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。

每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:

  • superblock:记录此 filesystem 的整体信息,包括 inode/block 的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
  • inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;
  • block:实际记录文件的内容,若文件太大时,会占用多个 block

由于每个 inode 与 block 都有编号,而每个文件都会占用一个 inode ,inode 内则有文件数据放置的 block 号码。因此,如果能够找到文件的 inode 的话,那么自然就会知道这个文件所放置数据的 block 号码, 当然也就能够读出该文件的实际数据了。这是个比较有效率的作法,因为如此一来磁盘就能够在短时间内读取出全部的数据, 读写的效能比较好。

将 inode 与 block 区块用图解来说明一下,如上图,文件系统先格式化出 inode 与 block 的区块,假设一个文件的属性和权限数据是放置到 inode 4 号,而这个 inode 记录了文件数据的实际放置点为 2,7,13,15 这四个 block 号码,此时操作系统就能够据此来排列磁盘的阅读顺序,可以一口气将四个 block 内容读出来。这种数据存取的方法称为索引式文件系统(indexed allocation)

那有没有其他的惯用文件系统可以比较一下啊? 有的,那就是我们惯用的随身碟(闪存),随身碟使用的文件系统一般为 FAT 格式。FAT 这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有 block 在一开始就读取出来。每个 block 号码都记录在前一个 block 当中, 他的读取方式有点像底下这样:

上图中我们假设文件的数据依序写入 1->7->4->15 号这四个 block 号码中, 但这个文件系统没有办法一口气就知道四个 block 的号码,他得要一个一个的将 block 读出后,才会知道下一个 block 在何处。 如果同一个文件数据写入的 block 分散的太过厉害时,则我们的磁盘读取头将无法在磁盘转一圈就读到所有的数据, 因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!

常常会听到所谓的『碎片整理』吧?需要碎片整理的原因就是文件写入的 block 太过于离散了,此时文件读取的效能将会变的很差所致。 这个时候可以透过碎片整理将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易啊! 想当然尔,FAT 的文件系统需要经常的碎片整理一下,那么 Ext2 是否需要磁盘重整呢?

由于 Ext2 是索引式文件系统,基本上不太需要常常进行碎片整理的。但是如果文件系统使用太久,常常删除/编辑/新增文件时,那么还是可能会造成文件数据太过于离散的问题,此时或许会需要进行重整一下的。

inode 的内容在记录文件的权限与相关属性,至于 block 区块则是在记录文件的实际内容。 而且文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs 等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动。但是如果仔细考虑一下,如果我的文件系统高达数百 GB 时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定,因为 inode 与 block 的数量太庞大,不容易管理。因此 文件系统在格式化的时候基本上是区分为多个区块群组(block group)的,每个区块群组都有独立的 inode / block / superblock 系统。

感觉上就好像我们在当兵时,一个营里面有分成数个连,每个连有自己的联络系统, 但最终都向营部回报连上最正确的信息一般!这样分成一群群的比较好管理啦!整个来说,文件系统格式化后有点像底下这样:

在整体的规划中,文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装开机管理程序,这是个非常重要的设计,因为如此一来我们就能够将不同的开机管理程序安装到个别的文件系统最前端,而不用覆盖整颗磁盘唯一的 MBR, 这样也才能够制作出多重引导的环境。

每一个区块群组(block group)的六个主要内容说明:

data block (资源区块)

data block 是用来放置文件内容数据的地方,在文件系统中所支持的block 大小有 1k, 2k, 4k 三种而已。在格式化时 block 的大小是固定了,且每个 block 都是有编号,以方便 inode 的记录不过要注意的是,由于 block 大小的差异,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量并不相同。 因为 block 大小而产生的 文件系统限制如下:

block 基本限制如下:

  1. block 的大小与数量在格式化完就不能再改变了;
  2. 每个 block 内最多只能够放置一个文件的数据;
  3. 如果文件大于 block 的大小,则一个文件会占用多个 block 数量;
  4. 若文件小于 block,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)

如上第四点所说,由于每个 block 仅能容纳一个文件的数据而已,因此如果你的文件都非常小,但是你的 block 在格式化时却选用最大的 4K 时,可能会产生一些容量的浪费喔!我们以底下的一个
简单例题来算一下空间的浪费吧!

什么情况会产生上述的状况呢?

例如 BBS 网站的数据啦!如果 BBS 上面的数据使用的是纯文本文件来记载每篇留言, 而留言内容如果都写上『如题』时,想一想,是否就会产生很多小文件了呢?

好,既然大的 block 可能会产生较严重的磁盘容量浪费,那么我们是否就将 block 大小订为 1K 即可? 这也不妥,因为如果 block 较小的话,那么大型文件将会占用数量更多的 block ,而 inode 也要记录更多的 block 号码,此时将可能导致文件系统不良的读写效能。

inode 是什么

文件存储在硬盘上,硬盘的最小存储单位叫做 “扇区(Sector)”。每个扇区储存 512 字节(相当于 0.5KB)

操作系统读取硬盘的时候,不会一个个扇区的读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个 sector组成一个 block。

文件数据都储存在"块"中,那么很显然,还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。

每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。

inode 的内容

inode包含文件的元信息,具体来说有以下内容:

  1. 文件的字节数
  2. 文件拥有者的User ID
  3. 文件的Group ID
  4. 文件的读、写、执行权限
  5. 文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。
  6. 链接数,即有多少文件名指向这个inode
  7. 文件数据block的位置

可以用stat命令,查看某个文件的inode信息:

总之,除了文件名以外的所有文件信息,都存在inode之中。至于为什么没有文件名,下文会有详细解释。

inode 大小

inode也会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。

每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。

查看每个硬盘分区的inode总数和已经使用的数量,可以使用df命令。

查看每个inode节点的大小,可以用如下命令:

注意:

  dumpe2fs 仅支持在 ext2/3/4 文件系统

  如果是 xfs 需要使用 xfs_info 查看

inode 号码

每个inode都有一个号码,操作系统用inode号码来识别不同的文件。

这里值得重复一遍,Unix/linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。

表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:

  1. 系统找到这个文件名对应的inode号码;
  2. 通过inode号码,获取inode信息;
  3. 根据inode信息,找到文件数据所在的block,读出数据

使用ls -i命令,可以看到文件名对应的inode号码:

目录文件

Unix/Linux系统中,目录(directory)也是一种文件。打开目录,实际上就是打开目录文件。

目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。

ls命令只列出目录文件中的所有文件名

ls -i命令列出整个目录文件,即文件名和inode号码:

如果要查看文件的详细信息,就必须根据inode号码,访问inode节点,读取信息。ls -l命令列出文件的详细信息。

理解了上面这些知识,就能理解目录的权限。目录文件的读权限(r)和写权限(w),都是针对目录文件本身(即不同用户能以什么权限访问操作对该目录文件,例如这里不同用户对tmp目录文件(d可以查出tmp是目录文件,d表示directory,即目录)分别为rwxr-xr-x,第一组的三个字符,即rwx,表示文件拥有者用户的对该文件的读写权限,第二组的三个字符,即r-x,表示文件拥有者用户所在的用户组里的其他用户对该文件的读写权限,第三组的三个字符,即r-x,表示文件拥有者用户所在的用户组以外的用户对该文件的读写权限。一个某个用户下运行的进程访问操作该目录文件只能以该用户所具有的对该目录文件的权限进行操作)。由于目录文件内只有文件名和inode号码,所以如果只有读权限,只能获取文件名,无法获取其他信息,因为其他信息都储存在inode节点中,而读取inode节点内的信息需要目录文件的执行权限(x)。

硬链接

一般情况下,文件名和inode号码是"一一对应"关系,每个inode号码对应一个文件名。但是,Unix/Linux系统允许,多个文件名指向同一个inode号码。

这意味着,可以用不同的文件名访问同样的内容;对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为"硬链接"(hard link)。

ln 命令可以创建硬链接:

ln 源文件 目标文件

运行上面这条命令以后,源文件与目标文件的inode号码相同,都指向同一个inode。inode信息中有一项叫做"链接数",记录指向该inode的文件名总数,这时就会增加1。

反过来,删除一个文件名,就会使得inode节点中的"链接数"减1。当这个值减到0,表明没有文件名指向这个inode,系统就会回收这个inode号码,以及其所对应block区域。

软链接

除了硬链接以外,还有一种特殊情况。

文件A 和 文件B 的 inode 号码虽然不一样,但是文件A 的内容是文件B 的路径。读取文件A时,系统会自动将访问者导向文件B。因此,无论打开哪一个文件,最终读取的都是文件B。这时,文件A就称为文件B的"软链接"(soft link)或者"符号链接(symbolic link)。

这意味着,文件A依赖于文件B而存在,如果删除了文件B,打开文件A就会报错:"No such file or directory"。这是软链接与硬链接最大的不同:文件A指向文件B的文件名,而不是文件B的inode号码,文件B的inode"链接数"不会因此发生变化。

inode 的特殊作用

由于inode号码与文件名分离,这种机制导致了一些Unix/Linux系统特有的现象。

(1)有时,文件名包含特殊字符,无法正常删除。这时,直接删除inode节点,就能起到删除文件的作用。

(2)移动文件或重命名文件,只是改变文件名,不影响inode号码。

(3)打开一个文件以后,系统就以inode号码来识别这个文件,不再考虑文件名。因此,通常来说,系统无法从inode号码得知文件名。

第3点使得软件更新变得简单,可以在不关闭软件的情况下进行更新,不需要重启。因为系统通过inode号码,识别运行中的文件,不通过文件名。更新的时候,新版文件以同样的文件名,生成一个新的inode,不会影响到运行中的文件。等到下一次运行这个软件的时候,文件名就自动指向新版文件,旧版文件的inode则被回收。

总结:

  1. 一个 inode 对应一个文件,而一个文件根据其大小,会占用多块 blocks;
  2. 更为准确的来说,一个文件只对应一个Inode。因为硬链接其实不是创建新文件,只是在Directory中写入了新的对应关系而已;
  3. 当删除文件时,只是把 inode 标记为可用,文件在block 中的内容是没有被清除的,只有在有新的文件需要占用block的时候,才会被覆盖。

文章参考自网络 和 《鸟哥私房菜》

参考链接:

https://www.cnblogs.com/doll-net/p/6090298.html
https://blog.csdn.net/Ohmyberry/article/details/80427492

猜你喜欢

转载自www.cnblogs.com/hukey/p/11693712.html
今日推荐