目录
[编辑 硬链接](#编辑 硬链接)
文件系统
内存文件与磁盘文件的区别
我们知道文件可以分为磁盘文件和内存文件,内存文件前面我们基础IO的相关内容,但是在上一篇文章中并没有详细指出这个概念,那么这里解释一下这个概念。
就拿我们的windows电脑,我们点开我们此电脑后,会看到我们的电脑会分C,D,E盘。其中磁盘文件 是存储在这些分区中的具体文件,例如文档、图片、视频、程序等。他们的存储特点是存储在持久化存储设备 (如硬盘、SSD等),些文件保存在磁盘分区中,即使计算机关机或重启,数据也不会丢失。
而与之相对的就是内存文件,其是存储在内存(RAM)中,访问速度快,但断电后数据丢失,适合临时数据。但这如果仅仅根据概念对于我们还是区分不清,那么我就把二者放一起进行解释。
-
磁盘文件被打开后:
-
当磁盘文件被打开时,操作系统会将文件的部分或全部数据从磁盘加载到内存(RAM)中。
-
这些数据在内存中的存在形式可以称为文件在内存中的表示 ,也就是你所说的内存文件。
-
-
数据的位置:
-
磁盘上:文件的原始数据仍然存在于磁盘上,并没有消失。
-
内存中:文件的数据被复制到内存中,以便程序可以快速访问和操作。
-
-
内存文件的临时性:
-
内存中的数据是磁盘数据的临时副本,只有在文件被打开时才会存在。
-
如果文件被修改,修改的内容会暂时保存在内存中,直到显式保存(写回磁盘)或关闭文件。
举个例子
-
-
你有一个存储在磁盘上的文本文件(磁盘文件)。
-
当你用记事本打开这个文件时,操作系统会将文件的内容加载到内存中(内存文件)。
-
你在内存中对文件进行编辑,修改的内容暂时保存在内存中。
-
如果你保存文件,修改的内容会从内存写回到磁盘,更新磁盘文件。
-
-
注意:内存文件是文件在内存中的表示,但它并不替代磁盘文件,而是与磁盘文件共存。
那么我们下面针对磁盘文件进行介绍吧。
初识inode
我们都知道文件由两部分构成,分别是文件内容与文件属性。当然磁盘文件也不例外也是由两部分构成:文件内容,文件属性。文件内容就是文件当中存储的数据,文件属性就是文件的一些基本信息,例如文件名、文件大小以及文件创建时间等信息都是文件属性,文件属性又被称为元信息。
在命令行当中输入ls -l
,即可显示当前目录下各文件的属性信息。
其中,各列信息所对应的文件属性如下: 在Linux操作系统中,inode 是一个非常重要的概念,它存储了文件的元信息(如文件大小、权限、所有者、时间戳等),但不包含文件名。每个文件都有一个唯一的 inode号,用于标识和管理文件的属性。所以inode具有唯一性,操作系统不会让其两个不相关或不同的文件具有同一个inode
比喻:图书馆中的书籍管理
我们可以用图书馆的例子来比喻Linux文件系统中inode的作用:
-
书籍(文件):
-
图书馆中有很多书,每本书相当于一个文件。
-
书的内容相当于文件的数据内容。
-
-
书籍的索引卡片(inode):
-
每本书都有一个索引卡片,记录了书的详细信息,比如书名、作者、出版日期、存放位置等。
-
这张索引卡片相当于文件的inode,存储了文件的元信息。
-
-
书籍的唯一编号(inode号):
-
每张索引卡片都有一个唯一的编号,用于快速找到对应的书籍。
-
这个编号相当于文件的inode号,是文件的唯一标识。
-
-
书籍的存放位置(数据块):
-
书籍的实际内容存放在图书馆的某个书架上。
-
书架的位置相当于文件的数据块,存储了文件的实际内容。
-
-
书籍的借阅记录(文件名):
-
读者通过书名来查找书籍,但书名并不是书籍本身,而是书籍的一个别名。
-
书名相当于文件的文件名,是用户访问文件的入口。
-
具体流程
-
当你查找一本书时,图书馆管理员会根据书名找到对应的索引卡片(文件名 -> inode)。
-
通过索引卡片上的编号(inode号),管理员可以快速定位书籍的存放位置(inode -> 数据块)。
-
最终,你可以拿到书籍的内容(文件数据)。
也就是说,inode是一个文件的属性集合,Linux中几乎每个文件都有一个inode,为了区分系统当中大量的inode,我们为每个inode设置了inode编号。
在命令行当中输入ls -i
,即可显示当前目录下各文件的inode编号。

磁盘的概念
那么首先第一个问题就是什么是磁盘?
从课本上的定义我们可以知道:磁盘是一种永久性存储介质,在计算机中,磁盘几乎是唯一的机械设备。与磁盘相对应的就是内存,内存是掉电易失存储介质,目前所有的普通文件都是在磁盘中存储的。
再学冯诺依曼体系的时候,我们就听过一句话磁盘在冯诺依曼体系结构当中既可以充当输入设备,又可以充当输出设备。

那么我们先跳出课本,从现实中认识一下磁盘。
这些都是磁盘

相信,使用过老式台式机电脑的都有过这样的体验,当我们开机时,电脑就出现有东西快速转动的情况,其实除了风扇外,磁盘也是在高速的运转着,他不停的转就是为了读取数据。 但是随着技术的发展,固态硬盘(SSD)逐渐取代了机械硬盘,提供了更快的速度和更安静的体验。
在磁盘高速转动过程中,磁盘的寻找方案就为如下
对磁盘进行读写操作时,一般有以下几个步骤:
- 确定读写信息在磁盘的哪个盘面。
- 确定读写信息在磁盘的哪个柱面。
- 确定读写信息在磁盘的哪个扇区。
通过以上三个步骤,最终确定信息在磁盘的读写位置。
所以说我们一个磁盘它会有好几个片,不同片之间可以理解为不同分区,同一个片内不同的同心圆下也可以理解为不同分区。
磁盘分区与格式化介绍
线性存储介质
理解文件系统,首先我们将磁盘所有的存储空间想象成一个线性的存储介质,想想磁带,当磁带被卷起来时,其就像磁盘一样是圆形的,但当我们把磁带拉直后,其就是线性的。
磁盘分区
将磁盘想象为线性存储 后,磁盘就可以被看作一个巨大的块设备 ,数据以扇区(Sector)为单位进行存储和访问。

计算机为了更好的管理磁盘,于是对磁盘进行了分区。磁盘分区就是使用分区编辑器在磁盘上划分几个逻辑部分,盘片一旦划分成数个分区,不同的目录与文件就可以存储进不同的分区,分区越多,就可以将文件的性质区分得越细,按照更为细分的性质,存储在不同的地方以管理文件,例如在Windows下磁盘一般被分为C盘和D盘两个区域。
同样在Linux操作系统中,我们也可以通过以下命令查看我们磁盘的分区信息:
ls /dev/vda* -l

磁盘格式化
当磁盘完成分区后,我们还需要对磁盘进行格式化。磁盘格式化就是对磁盘中的分区进行初始化的一种操作,这种操作通常会导致现有的磁盘或分区中所有的文件被清除。 这一步就好比我们在重装操作系统时,通常需要对系统分区(如C盘)进行格式化,以清除旧系统的文件和设置,为新系统提供一个干净的环境。
简单来说,磁盘格式化就是对分区后的各个区域写入对应的管理信息。
其中,写入的管理信息是什么是由文件系统决定的,不同的文件系统格式化时写入的管理信息是不同的,常见的文件系统有EXT2、EXT3、XFS、NTFS等。
小扩展:
但是实际上我们在磁盘上创建一个文件,其实操作系统和磁盘会进行以下操作:
分配空间:
- 文件系统会查找空闲的扇区(或块),并分配给新文件。
写入数据:
- 磁头会移动到分配的扇区,将文件的数据写入磁盘。
更新元数据:
- 文件系统会更新元数据(如inode、FAT表等),记录文件的位置、大小、权限等信息。
同样磁头会在在磁盘上做一些操作然后使得磁盘上发生了一些改变我们磁盘上才会存储这个文件。
当你删除一个文件时,操作系统和磁盘并不会真正清除文件的数据,而是通过以下方式"标记"文件为已删除:
标记元数据:
- 文件系统会将文件的元数据标记为"已删除"(例如在FAT文件系统中,将目录项的第一个字节改为特殊值;在NTFS中,将MFT条目标记为未使用)。
释放空间:
- 文件系统会将文件占用的扇区标记为"空闲",允许其他文件使用这些空间。
数据残留:
- 文件的实际数据仍然保留在磁盘上,直到这些扇区被新数据覆盖。
同样磁盘上还是存有清楚前的痕迹。所以说如果我们将一个文件刚刚清楚后,是可以通过专业的操作将其文件恢复。但者专业操作一般是找专业的厂家要做,很麻烦,所以备份很重要。
EXT2文件系统的存储方案
计算机为了更好的管理磁盘,会对磁盘进行分区。而对于每一个分区来说,分区的头部会包括一个启动块(Boot Block),对于该分区的其余区域,EXT2文件系统会根据分区的大小将其划分为一个个的块组(Block Group)。注意: 启动块的大小是确定的,而块组的大小是由格式化的时候确定的,并且不可以更改。
其次,每个块组都有着相同的组成结构,每个块组都由超级块(Super Block)、块组描述符表(Group Descriptor Table)、块位图(Block Bitmap)、inode位图(inode Bitmap)、inode表(inode Table)以及数据表(Data Block)组成。

Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被 划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设 定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的,
- Super Block(超级块)
-
作用:
-
超级块是文件系统的核心数据结构,记录了整个文件系统的全局信息。
-
它包含了文件系统的基本属性,例如:
-
Data Block和inode的总量。
-
未使用的Data Block和inode的数量。
-
Data Block和inode的大小。
-
文件系统的状态(如挂载时间、写入时间、检验时间等)。
-
-
-
重要性:
-
如果超级块被破坏,文件系统将无法正常挂载和访问。
-
但同一个分组内,不同的块组都有超级块,所以一个超级快被破坏,还可以由与他最相近的块组的超级块复原。
-
文件系统通常会在每个块组中备份一个Super Block,以防止主Super Block损坏。
-
但只有第一个块组中的Super Block是主Super Block,其他块组中的Super Block是备份。
-
现代文件系统(如ext3/ext4)通常会有多个超级块的备份,以防止数据丢失。
-
- Group Descriptor Table(块组描述符表)
-
作用:
-
文件系统通常被划分为多个块组(Block Group),每个块组包含一定数量的Data Block和inode。
-
块组描述符表记录了每个块组的属性信息,例如:
-
块组中Data Block和inode的使用情况。
-
块组中空闲Data Block和inode的数量。
-
块组中位图(Block Bitmap和inode Bitmap)的位置。
-
-
-
重要性:
- 块组描述符表帮助文件系统快速定位和管理每个块组的资源。
- Block Bitmap(块位图)
-
作用:
-
块位图是一个二进制位图,用于记录每个Data Block的使用情况。
-
每个位(bit)对应一个Data Block:
-
1
表示该Data Block已被占用。 -
0
表示该Data Block空闲。
-
-
-
重要性:
- 块位图帮助文件系统快速找到空闲的Data Block,用于存储新文件的数据。
- inode Bitmap(inode位图)
-
作用:
-
inode位图是一个二进制位图,用于记录每个inode的使用情况。
-
每个位(bit)对应一个inode:
-
1
表示该inode已被占用。 -
0
表示该inode空闲。
-
-
-
重要性:
- inode位图帮助文件系统快速找到空闲的inode,用于存储新文件的元数据。
- inode Table(inode表)
-
作用:
-
inode表存储了每个文件的元数据(即inode),例如:
-
文件的大小、权限、所有者、时间戳等。
-
文件数据块的指针(指向Data Blocks)。
-
-
-
重要性:
- inode表是文件系统的核心组成部分,通过inode可以找到文件的所有数据块。
- Data Blocks(数据块)
-
作用:
-
数据块是实际存储文件内容的地方。
-
文件的数据被分割成多个块,存储在不同的Data Blocks中。
-
-
重要性:
-
数据块是文件系统的最终目标,所有文件的内容都存储在这里。
-
比喻:图书馆的管理系统
我们可以用图书馆的例子来比喻文件系统的各个组成部分:
-
超级块(Super Block):
-
相当于图书馆的总管理办公室,记录了整个图书馆的全局信息,例如:
-
图书馆的总书架数量(Data Block总量)。
-
空闲书架的数量(未使用的Data Block)。
-
每个书架的大小(Data Block大小)。
-
图书馆的开放时间、最近一次整理时间等。
-
-
-
块组描述符表(Group Descriptor Table):
-
相当于每个楼层的管理办公室,记录了该楼层的详细信息,例如:
-
该楼层的书架数量(块组中的Data Block)。
-
空闲书架的数量(未使用的Data Block)。
-
书架的使用情况(Block Bitmap)。
-
-
-
块位图(Block Bitmap):
- 相当于每个楼层的书架使用情况表,记录了每个书架是否被占用。
-
inode位图(inode Bitmap):
- 相当于每本书的借阅记录表,记录了每本书是否被借出。
-
inode表(inode Table):
- 相当于每本书的详细信息卡片,记录了书的属性(如书名、作者、出版日期等)以及书的位置(书架编号)。
-
数据块(Data Blocks):
- 相当于书架上的书籍,是实际存储内容的地方。
注意:
因为inode是有唯一性的特点所以磁盘分区并格式化后,每个分区的inode个数就确定了,操作系统不会创建两个一样的inode来标识不同的文件。
如何理解创建一个文件?
我们了解了文件系统后就得知创建一个文件是操作系统大概做了什么
- 通过遍历inode位图的方式,找到一个空闲的inode。
- 在inode表当中找到对应的inode,并将文件的属性信息填充进inode结构中。
- 将该文件的文件名和inode指针添加到目录文件的数据块中。
如何理解对文件写入信息?
- 通过文件的inode编号找到对应的inode结构。、
- 通过inode结构找到存储该文件内容的数据块,并将数据写入数据块。
- 若不存在数据块或申请的数据块已被写满,则通过遍历块位图的方式找到一个空闲的块号,并在数据区当中找到对应的空闲块,再将数据写入数据块,最后还需要建立数据块和inode结构的对应关系。
说明一下:
一个文件使用的数据块和inode结构的对应关系,是通过一个数组进行维护的,该数组一般可以存储15个元素,其中前12个元素分别对应该文件使用的12个数据块,剩余的三个元素分别是一级索引、二级索引和三级索引,当该文件使用数据块的个数超过12个时,可以用这三个索引进行数据块扩充。
如何理解删除一个文件?
- 将该文件对应的inode在inode位图当中置为无效。
- 将该文件申请过的数据块在块位图当中置为无效。
因为此操作并不会真正将文件对应的信息删除,而只是将其inode号和数据块号置为了无效,所以当我们删除文件后短时间内是可以恢复的。
为什么拷贝文件的时候很慢,而删除文件的时候很快?
因为拷贝文件需要先创建文件,然后再对该文件进行写入操作,该过程需要先申请inode号并填入文件的属性信息,之后还需要再申请数据块号,最后才能进行文件内容的数据拷贝,而删除文件只需将对应文件的inode号和数据块号置为无效即可,无需真正的删除文件,因此拷贝文件是很慢的,而删除文件是很快的。
这就像建楼一样,我们需要很长时间才能建好一栋楼,而我们若是想拆除一栋楼,只需在这栋楼上写上一个"拆"字即可。
如何理解目录
-
目录的本事也是文件,但是一种特殊文件:
-
目录在Linux中被视为一种特殊类型的文件,它有自己的inode和数据块。
-
目录的inode存储了目录的元数据(如权限、所有者、大小等)。
-
目录的数据块存储了目录的内容,即该目录下的文件名和对应文件的inode指针。
-
-
inode的作用:
-
每个目录都有一个唯一的inode,存储了目录的元数据,例如:
-
目录的大小。
-
目录的权限(读、写、执行)。
-
目录的所有者和所属组。
-
目录的时间戳(创建时间、修改时间等)。
-
目录的数据块指针(指向存储目录内容的数据块)。
-
-
扩充:
在Linux文件系统中,文件名 并不是存储在文件自己的inode中,而是存储在目录的文件内容 中。这是因为Linux文件系统的设计理念是将文件名与文件内容分离,文件名只是用户访问文件的一个"别名",而文件的实际内容和管理信息是通过inode来处理的。
所以对于用户当输入自己想要查看的文件名时,操作系统会通过文件名访问文件时,文件系统会先查找目录的数据块,找到文件名对应的inode号。然后通过inode号找到文件的inode,进而访问文件的内容和属性。
软硬链接
首先明确一点软连接的格式就是 ...-s,硬链接是...-h
软连接
我们可以通过以下命令创建一个文件的软连接。
ln -s test test-s
通过
ls -i -l
命令我们可以看到,软链接文件的inode号与源文件的inode号是不同的,并且软链接文件的大小比源文件的大小要小得多。
软链接又叫做符号链接,软链接文件相对于源文件来说是一个独立的文件,该文件有自己的inode号,但是该文件只包含了源文件的路径名,所以软链接文件的大小要比源文件小得多。软链接就类似于Windows操作系统当中的快捷方式。
但是软链接文件只是其源文件的一个标记,当删除了源文件后,链接文件不能独立存在,虽然仍保留文件名,但却不能执行或是查看软链接的内容了。就好比我们把vscode删了后,只留下桌面图标,双击也再也打不开了。

当我们再运行时也会报错
硬链接
我们可以通过以下命令创建一个文件的硬连接。
ln test test-h

通过ls -i -l
命令我们可以看到,硬链接文件的inode号与源文件的inode号是相同的,并且硬链接文件的大小与源文件的大小也是相同的,特别注意的是,当创建了一个硬链接文件后,该硬链接文件和源文件的硬链接数都变成了2。
硬链接文件就是源文件的一个别名,一个文件有几个文件名,该文件的硬链接数就是几,这里inode号为924344的文件有myproc和myproc-h两个文件名,因此该文件的硬链接数为2。
与软连接不同的是,当硬链接的源文件被删除后,硬链接文件仍能正常执行,只是文件的链接数减少了一个,因为此时该文件的文件名少了一个。
总之,硬链接就是让多个不在或者同在一个目录下的文件名,同时能够修改同一个文件,其中一个修改后,所有与其有硬链接的文件都一起修改了。
为什么刚刚创建的目录的硬链接数是2?
我们创建一个普通文件,该普通文件的硬链接数是1,因为此时该文件只有一个文件名。那为什么我们创建一个目录后,该目录的硬链接数是2?
其实观察仔细,我们创建一个空目录的情况下,打开进入该目录,该目录还会有两个文件,分别是 ./ 与 ../。所以每个目录创建后,该目录下默认会有两个隐含文件./ 和../,它们分别代表当前目录和上级目录,因此这里创建的目录有两个名字,一个是dir另一个就是该目录下的.,所以刚创建的目录硬链接数是2。同样通过观察其是统一个inode
软硬链接的区别
- 软链接是一个独立的文件,有独立的inode,而硬链接没有独立的inode。
- 软链接相当于快捷方式,硬链接本质没有创建文件,只是建立了一个文件名和已有的inode的映射关系,并写入当前目录。
文件的三个时间
在Linux当中,我们可以使用命令stat 文件名
来查看对应文件的信息。

这其中包含了文件的三个时间信息:
- Access Time(atime): 文件最后被访问的时间。
- Modify Time(mtime): 文件内容最后的修改时间。
- Change Time(ctime): 文件属性最后的修改时间。
当我们修改文件内容时,文件的大小一般也会随之改变,所以一般情况下Modify的改变会带动Change一起改变,但修改文件属性一般不会影响到文件内容,所以一般情况下Change的改变不会带动Modify的改变。
这是因为
从操作系统的优化角度来看,这是为了提高效率 和减少不必要的操作:
性能优化:
修改文件属性(如权限、所有者)是一个轻量级操作,只需要更新inode中的元数据。
如果每次修改属性都强制更新文件内容的时间戳(mtime),会导致额外的磁盘写入操作,降低性能。
逻辑分离:
文件内容和文件属性是逻辑上分离的。修改属性并不影响文件的实际数据,因此没有必要更新内容的时间戳。
这种分离设计使得文件系统可以更高效地管理文件和元数据。
用户期望:
- 用户通常认为修改文件属性(如权限)不会影响文件内容。如果修改属性导致内容时间戳更新,可能会让用户感到困惑。
我们若是想将文件的这三个时间都更新到最新状态,可以使用命令touch 文件名来进行时间更新。
注意: 当某一文件存在时使用touch命令,此时touch命令的作用变为更新文件信息。
使用touch
命令更新时间戳
-
touch
命令的作用:-
当文件不存在 时,
touch
会创建一个空文件。 -
当文件存在 时,
touch
会更新文件的时间戳。
-
-
更新时间戳:
-
默认情况下,
touch
会更新文件的atime 和mtime。 -
可以使用选项来指定更新时间戳:
-
-a
:只更新atime。 -
-m
:只更新mtime。 -
-c
:如果文件不存在,则不创建文件。 -
-t
:指定时间戳(格式为[[CC]YY]MMDDhhmm[.ss]
)。
-
-
更新文件的atime 和mtime:
touch filename
只更新文件的mtime:
touch -m filename
只更新文件的atime:
touch -a filename
指定时间戳:
touch -t 202310101200.00 filename