🌈 个人主页:Zfox_
🔥 系列专栏:Linux
目录
- [🚀 前言](#🚀 前言)
- [一: 🔥 磁盘的物理结构](#一: 🔥 磁盘的物理结构)
- [二: 🔥 磁盘的存储结构](#二: 🔥 磁盘的存储结构)
- [三: 🔥 磁盘的逻辑结构](#三: 🔥 磁盘的逻辑结构)
- [四: 🔥 理解文件系统(重)](#四: 🔥 理解文件系统(重))
- [五: 🔥 软硬链接(重)](#五: 🔥 软硬链接(重))
-
- [🥝 5.1 软硬链接的创建](#🥝 5.1 软硬链接的创建)
- [🥝 5.2 软硬链接的区别](#🥝 5.2 软硬链接的区别)
- [🥝 5.3 软硬链接的应用](#🥝 5.3 软硬链接的应用)
-
- [🦋 软链接](#🦋 软链接)
- [🦋 硬链接](#🦋 硬链接)
- [六:🔥 共勉](#六:🔥 共勉)
🚀 前言
🦁 上一篇博客 【Linux】文件IO深度解析:文件描述符与重定向的奥秘 讲的 FILE 也是文件,是打开文件。那么未被打开文件,也是放在磁盘上,磁盘上有大量的文件也是必须被静管理的,方便我们随时打开,这也是文件系统。文件系统既要管理动态打开文件,又要管理静态未被打开文件。文件是放在磁盘的,我们对于磁盘是陌生的。下面我们就会先了解硬件 -- 磁盘,然后再来学习文件系统。
一: 🔥 磁盘的物理结构
硬盘是什么样子:
磁盘是如何动的:
🍃 磁头摆动和盘片旋转是通过马达控制的,我们可以通过硬件电路组成伺服系统给磁盘发二进制指令,然后让磁盘定位去寻址某个特定的区域,然后从磁盘上读取数据。磁盘和磁头都有两面,两面都是可以进行读写数据的。
🍃 磁头和盘片是没有接触的!他们的距离就像一架波音757隔着1米的距离在飞行。而且磁盘是不能有一点灰尘的,就好像飞机飞行前没有障碍物一样。所以磁盘必须得防止抖动,一旦磁头和盘面接触就会使得盘面刮花,丢失数据
🍃 硬件上保存二进制,是跟对应的设备有关,寄存器和内存是通过触发器电脉冲,对硬件设备进行带点或者失电,通过电路的有无来代表二进制。每一个寄存器触发器存储单元,每一个单元都是硬件电路,他们都可以进行存放电的。。
🍃 在不同的设备,表示二进制的方式也是不同的,在网络里面通过信号的有无,通过信号的疏密来表示 01。
🍃 这里可以理解磁头通过带放电,对磁盘某一个位置进行 N/S 极互换,就完成了 0/1 的写入,如果需要写入 512比特位,就相当于触电 523 次。-- 磁化技术
二: 🔥 磁盘的存储结构
🦁 我们看到盘面是非常光滑的,但是在放大下,磁道和磁道之间是有间隙的。在微观下,一个扇区可存大量的电子。
磁盘寻址的基本单位是扇区(512byte),虽然越靠近圆心外侧面积越大,但是可以通过工艺进行不同扇区的密度大小进行调解,所以每个扇区存储都是512 byte。不考虑其他情况。
在单面中定位一个扇区:
-
磁头来回摆动确认磁道,盘片旋转确定扇区。
-
在立体视图中,有的时候会磁道就等于柱面,磁头和扇面不变。磁头是共同进退的 - 同时进行寻找磁道。
在磁盘中定位一个扇区:
- 先定位在哪一个磁道,再定位磁头(盘面),最后定位在那个扇区。
三: 🔥 磁盘的逻辑结构
当把磁带扯直,我们就可以把它看成一条瘦长的矩形,这条矩形中存放这数据。磁盘其实也是一样,我们将磁盘中磁道拉直,也就变成矩形,里面存在着大量的数据。我们就可以把它想象成线性结构。
🐲 上述是对于一条磁道,那么多块磁盘呢?一般电脑选择的500GB,500GB是可以分盘的CDEF。那么我们就可以抽象化将不同盘面想象成一块数据,整个磁盘看做一个数组 sector arr[n],这样就方便对磁盘进行管理。
对磁盘进行管理就变成了对数组进行管理。CHS寻址模式将硬盘划分为柱面(Cylinder)、磁头(Heads)、扇区(Sector)。那在操作系统中我们就可以通CHS进行查找(方法)。
访问一个扇区是512字节,如果将磁盘的访问的基本单位设置512字节,对于IO访问来说效率太低,一般是对8个扇区进行同时访问,OS内的文件系统定制的进行多个扇区的读取4KB为基本单位即使是指向读取/修改1bit,那么必须将4KB load内存,进行读取或者修改,如果必要,在写回磁盘
内存是被划分成为了4KB大小的空间--页框;磁盘中的文件尤其是可执行文件是按照4KB大小划分好的块--页帧,磁盘向内存拷贝数据,实质也是页帧将数据拷贝到页框中。
不管是拷贝数据还是修改数据,那么最开始都是需要将数据管理起来,这里我们通过分治的思想,一级一级的到向下一层减少管理空间,我们将最底层管理,对于上层而言也就是重复的工作了。所以理解文件管理我们就开始从这5GB开始(自定义5GB)。
四: 🔥 理解文件系统(重)
我们使用ls -l的时候看到的除了看到文件名,还看到了文件元数据。
cpp
[lisi@hcss-ecs-a9ee lesson22]$ ls -l
total 8
-rw-rw-r-- 2 lisi lisi 0 Oct 20 16:00 file-hard.link
lrwxrwxrwx 1 lisi lisi 8 Oct 20 16:03 file-soft.link -> file.txt
-rw-rw-r-- 2 lisi lisi 0 Oct 20 16:00 file.txt
drwxrwxr-x 3 lisi lisi 4096 Oct 21 20:00 other
drwxrwxr-x 3 lisi lisi 4096 Oct 21 19:47 stdio
每行包含7列:
cpp
-rw-rw-r-- 2 lisi lisi 0 Oct 20 16:00 file-hard.link
模式 硬链接数 文件所有者 组 大小 最后修改时间 文件名
ls -l 读取存储在磁盘上的文件信息,然后显示出来,为什么它能分开显示呢?我们知道:
文件 = 内容 + 属性
🐮 linux的文件属性和文件内容是分批储存的,如下所示:
一个文件属性的,文件的大小,权限,等等信息在都在Inode中。
其实这个信息除了通过ls -l方式来读取,还有一个stat命令能够看到更多信息
cpp
[lisi@hcss-ecs-a9ee lesson22]$ stat test.c
File: 'test.c'
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd01h/64769d Inode: 656174 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1005/ hongxin) Gid: ( 1005/ hongxin)
Access: 2023-01-16 15:44:36.036230458 +0800
Modify: 2023-01-16 15:44:36.036230458 +0800
Change: 2023-01-16 15:44:36.036230458 +0800
Birth: -
在这里也显示I/O块为4kb,也就再次证实磁盘的访问的基本单位4kb(大多数操作系统)。
上面的执行结果有信息需要解释清楚 inode,为了能解释清楚inode我们先简单了解一下文件系统。我们也知道了解文件系统就应该了解最底层这空间大小:
Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被 划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。
-
启动块-Boot Block:大小就是1kB,由PC标准规定,用来存储磁盘分区的信息和启动信息,任何文件系统都不能使用该块。(如果这个块损坏,整个文件系统也就启动不起来了)。操作系统的开机,加电,启动相关的信息都是在这个块中的。
-
Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。
-
超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的 block 和 inode 的数量,一个 block 和 inode 的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block 的信息被破坏,可以说整个文件系统结构就被破坏了。
-
inode 节点表:存放文件属性 如 文件大小,所有者,最近修改时间等
-
正常情况下,保存的整个文件系统的信息不应该放在分区的最开始吗,为什么会在多个分组中存在呢,这里是为了备份,当文件受损时,就可以将其他分组的Super Block拷贝到当前,文件系统就得到恢复。
在学习下面内容之前,我们还是得对文件内容和属性深一步挖掘。我们知道文件是有文件内容和属性构成的,文件属性和文件内容是分批存储的。
文件内容:
- data block就是存放文件内容,它的特性就是随着应用类型的变化,大小在变化。
文件属性:
- ionde就是用来存储文件属性的,inodo属性信息不仅仅包括文件大小,属主,用户组,文件权限,修改时间,类型。还包含指向文件实体的指针功能,但是inode里面不包含文件名。inode的大小也是固定的。ionde为了区分彼此,每个inode都有自己的ID。
通过输入ls -li,我们发现他们文件的inode是不一样的。
cpp
[lisi@hcss-ecs-a9ee lesson22]$ ls -li
total 0
926813 -rw-rw-r-- 1 hongxin hongxin 0 Jan 16 19:49 log.txt
926812 -rw-rw-r-- 1 hongxin hongxin 0 Jan 16 19:47 test.c
inode表(inode Table) :
- 保存了分组内部所有可用的(已经使用+未被使用)inode。当我们创建一个文件时,第一时间找的就是inode Table,将文件属性如文件大小,所有者,最近修改时间等存放在这个表中。
inode位图(inode Bitmap):
- 每个bit表示一个inode是否空闲可用。
例如:0000001
位图中比特位的位置和当前文件对应的inode位置是一一对应的。比特位的位置代表的是它是第几个inode,比特位为0 ,代表inode未被占用,比特位为1,代表inode被占用。通过比特位的偏移位置去找inode Table去找到该inode(inode自己的编号),增加属性等操作 。
块位图(Block Bitmap):
- Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
块组描述符GDT(Group Descriptor Table):对应分组的宏观的属性信息,
查找文件属性和内容原理
如何查找文件属性和内容,首先我们需要知道inode编号是如何形成的:
每个区都有自己编号,例如:Block group 0-Block group n: 1000-10000 ,每个区都有自己的组,组会通过比特位图进行增加值,例如:起始1000,当新建一个inode,那么比特位图就加1:1001,你从01也可以得知在inode table中,它是第一个建立的ionde。
查找文件属性:实质就是从文件中找到inode编号,然后通过inode编号找到inode Table。
我们知道ionde Table后,又是如何通inode查找dateblocks呢?如图所示:
在struct_ionde中,通过data数组找到相应的数据块,这里特别需要注意的是,0-11是特指,而12-14是泛指。例如12指向一个数据块,这块数据块可以指向其他块数据块,这个块数据块保存的是其他数据块的地址。如果12不够用,例如13就可以指向其他数据块,其他数据块又保存其他数据块的地址。12是一级索引,13就是二级索引。
最后在这里需要了解:删除一个文件,直接将inode和block比特位清零即可-惰性删除。
建新文件操作
新文件操作将属性和数据分开存放的想法看起来很简单,但实际上是如何工作的呢?我们在通过touch一个新文件来看看如何工作。
cpp
[lisi@hcss-ecs-a9ee ~]$ touch abc
[lisi@hcss-ecs-a9ee ~]$ ls -i abc
263466 abc
通过上面ls -i abc 我们可以发现文件名是不在ionde中的,不属于文件属性管的。我们查找文件通过的文化名,这个是因为目录的数据块放的是当前目录下的文件名和inode的映射关系。所以我们就可以通过文件名来查找文件信息。
为了说明问题,将上图简化:
建一个新文件主要有一下4个操作:
- 存储属性
内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。
- 存储数据
该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据复制到300,下一块复制到500,以此类推。
- 记录分配情况
文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。
- 添加文件名到目录
新的文件名abc。linux如何在当前的目录中记录这个文件?内核将入口(263466,abc)添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起
最后为了避免知识混淆,我们汇聚一幅图,需要理解的是向磁盘进行I/O前,操作系统会读取该文件内容和属性,再进行加载(读取也要结合自身的操作)。
五: 🔥 软硬链接(重)
🥝 5.1 软硬链接的创建
我们先创建一个软链接文件,输入 ln -s myfile.c soft_file.link
[lisi@hcss-ecs-a9ee tmp]$ ln -s myfile.c soft_file.link
lrwxrwxrwx :l -- 是文件类型,链接文件
再查看inode,他们都有自己独立的inode,说明他们都是一个独立的文件。
我们再建立一个硬链接文件,输入ln myfile.c hard_file.link ,发现hard_file.link和 myfile.c的数字变成了2。
再查看inode,它的inode数是一样的。
为什么硬链接没有独立inode呢?我们通过测试来理解。
最开始我们没有给文件写入数据时,文件的大小为0
cpp
[lisi@hcss-ecs-a9ee tmp]$ ls -li
total 0
1838455 -rw-rw-r-- 2 lisi lisi 0 Oct 25 20:43 hard_file.link
1838455 -rw-rw-r-- 2 lisi lisi 0 Oct 25 20:43 myfile.c
1838456 lrwxrwxrwx 1 lisi lisi 8 Oct 25 20:43 soft_file.link -> myfile.c
当我们给myfile.c写入时,文件的大小一起变成了12,再给hard_file.link 写入时,他们文件大小一起变成了24。不管是myfile.c还是hard_file.link写入时,他们大小都会变成一样的。
cpp
[lisi@hcss-ecs-a9ee tmp]$ echo "hello link" >> myfile.c
[lisi@hcss-ecs-a9ee tmp]$ ls -li
total 8
1838455 -rw-rw-r-- 2 lisi lisi 12 Oct 25 20:47 hard_file.link
1838455 -rw-rw-r-- 2 lisi lisi 12 Oct 25 20:47 myfile.c
1838456 lrwxrwxrwx 1 lisi lisi 8 Oct 25 20:43 soft_file.link -> myfile.c
cpp
[lisi@hcss-ecs-a9ee tmp]$ echo "hello link" >> hard_file.link
[lisi@hcss-ecs-a9ee tmp]$ ls -li
total 8
1838455 -rw-rw-r-- 2 lisi lisi 24 Oct 25 20:48 hard_file.link
1838455 -rw-rw-r-- 2 lisi lisi 24 Oct 25 20:48 myfile.c
1838456 lrwxrwxrwx 1 lisi lisi 8 Oct 25 20:43 soft_file.link -> myfile.c
相信大家心里已经有答案了,为了再次确认我们再看看他们文件的内容。所以实则hard_file.link和cat myfile.c 都是cat myfile.c 文件。
[lisi@hcss-ecs-a9ee tmp]$ cat hard_file.link
hello link
hello link
hello link
[lisi@hcss-ecs-a9ee tmp]$ cat myfile.c
hello link
hello link
hello link
cpp
# 修改软链接
ln -sf test2.txt test_link
🥝 5.2 软硬链接的区别
软链接有独立的inode,可被当做独立文件看待。硬链接没有独立的inode,那么建立一个硬链接就是在指定路径下,新增文件名和inode编号的映射关系!
在shell中的做法 ,硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件。
cpp
1838455 -rw-rw-r-- 2 lisi lisi 24 Oct 25 20:48 hard_file.link
1838455 -rw-rw-r-- 2 lisi lisi 24 Oct 25 20:48 myfile.c
1838456 lrwxrwxrwx 1 lisi lisi 8 Oct 25 20:43 soft_file.link -> myfile.c
在硬链接中,那个链接数使用计数器,有一个文件指向myfile.c,count++。所以链接数为2,再有文件硬链接myfile.c,count++,所以链接数为2。
链接失效
硬链接的硬链接数变成1了,然后 cat hard_file.link 文件还有数据。
cpp
[lisi@hcss-ecs-a9ee tmp]$ 2023-1-17]$ cat hard_file.link
hello link
hello link
hello link
**真正删除一个文件,文件的硬链接数0的时候这个文件才算真正被删除。**所以这个硬链接就好比重命名
我们发现软件连接文件变红了,那个这个文件还存在吗?答案是存在的,虽然myfile.c文件删除了但是soft_file.link -> myfile.c的 ionde 还是在的,因为我们访问一个文件是通过文件名路径进行访问的,删除了myfile.c 破坏了 soft_file.link -> myfile.c 的文件名,这个文件名是在上级目录中存放的。
我们再重新新建myfile.c,让文件路径完整,但是我们发现这个文件是新的文件了, myfile.c中也没有数据了。
我们删除软链接,是不影响链接的文件的。删除软链接: unlink soft_file.link
cpp
[lisi@hcss-ecs-a9ee tmp]$ unlink soft_file.link
[lisi@hcss-ecs-a9ee tmp]$ ll
total 8
-rw-rw-r-- 1 lisi lisi 24 Oct 25 20:48 hard_file.link
-rw-rw-r-- 1 lisi lisi 3 Oct 25 21:05 myfile.c
小结:
- 软链接是一个特殊的独立文件,它内容记录源文件位置;硬链接只是源文件的引用,不占用实际空间。
- 删除软链接不影响源文件:删除源文件,软链接失效。删除硬链接不影响源文件,需将源文件和全部硬链接删除,源文件才会删除(换句话说,对于硬链接来说,删除了源文件,访问硬链接依旧有效)。
- 软链接可以跨分区;硬链接不能跨文件系统。
- 软链接可以针对目录;硬链接不能针对目录。
🥝 5.3 软硬链接的应用
🦋 软链接
我们在目录下建立test文件,然后随便写上端代码,生成可执行文件。
当我们cd ...退出,在其他文件执行时,需要记住文件路径,发现是非常麻烦的!
我们就可以建立软链接,在当前文件下直接执行。
这里的软链接好比是Windows下的快捷方式。
🦋 硬链接
我们先在创建一个文件file.txt,然后在创建一个目录empty。
cpp
[lisi@hcss-ecs-a9ee tmp]$ touch file.txt
[lisi@hcss-ecs-a9ee tmp]$ mkdir empty
我们发现目录的链接数是2,普通文件连接数是1,这是为什么呢?
因为普通文件本身有一个文件名和自己的inode具有一个映射关系。
关于目录empty,我们发现empty中他不关有自己当前路径,还有他的上级路径 ...。
cpp
[lisi@hcss-ecs-a9ee tmp]$ cd empty/
[lisi@hcss-ecs-a9ee empty]$ ls -lia
total 8
1838456 drwxrwxr-x 2 lisi lisi 4096 Oct 25 21:07 .
1838454 drwxrwxr-x 3 lisi lisi 4096 Oct 25 21:07 ..
[lisi@hcss-ecs-a9ee empty]$ cd ..
[lisi@hcss-ecs-a9ee tmp]$ ls -lia
total 12
1838454 drwxrwxr-x 3 lisi lisi 4096 Oct 25 21:07 .
1573076 drwx------ 12 lisi lisi 4096 Oct 25 20:42 ..
1838456 drwxrwxr-x 2 lisi lisi 4096 Oct 25 21:07 empty
1838455 -rw-rw-r-- 1 lisi lisi 0 Oct 25 21:07 file.txt
./代表当前路径,cd..代表返回上级路径。 这个.就相当于是empty的硬链接。这个..就是上级目录中的硬链接。
最后一点注意:系统不让用户给普通文件建立硬链接的原因是,害怕文件出现死循环。这个./...系统默认创建的。
六:🔥 共勉
以上就是我对 【Linux】万字长文带你深入理解文件系统与软硬链接
的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉