📝前言:
这篇文章我们来理解一下Linux文件系统
🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏
这里写目录标题
- 一,理解硬件
-
- [1. 物理结构](#1. 物理结构)
- [2. 逻辑结构](#2. 逻辑结构)
- 二,文件系统
-
- [1. 文件系统基本概念](#1. 文件系统基本概念)
- [2. ext2 文件系统](#2. ext2 文件系统)
- [3. 理解一](#3. 理解一)
- [4. 目录与文件名及路径解析](#4. 目录与文件名及路径解析)
- [5. 路径缓存](#5. 路径缓存)
- [6. 挂载分区](#6. 挂载分区)
- [7. 总结](#7. 总结)
- 三,软硬链接
-
- [1. 软链接](#1. 软链接)
- [2. 硬链接](#2. 硬链接)
一,理解硬件
在学习文件系统之前,我们需要先了解一下磁盘这个机械外设,在这里我不过多讲解,可能看看这篇文章。我提取并补充一些重要的知识:
1. 物理结构
物理结构基本了解:
- 磁头 用于在磁盘上寻址(定位磁道和定位扇区),所有磁头由机械臂杆控制,是共进退的
- 往磁盘写入,本质上就是在改变盘片上"颗粒"(最小存储单元)的南北极 / 高低电平...(这些具有两态性的,能表示 0 / 1的)
- 扇区:是磁盘存储数据的基本单位 ,512字节,块设备
- 如果要改一个扇区的一个bit位,OS都得把一整个扇区的512个字节全部加载到内存里,修改完那一个bit后再写回
- 如何寻找扇区(CHS定址方法)
- 磁头先选柱面(Cylinder)
- 再确定是哪一个盘面上的磁头(Head)
- 然后等待磁盘旋转,等到对应扇区(Sector)转到在磁头下
- 磁盘容量 = 磁头数 × 磁道(柱⾯)数 × 每道扇区数 × 每扇区字节数
2. 逻辑结构
逻辑结构基本了解:
- 某⼀个磁道展开,是一个一维数组
- 某一柱面的所有磁道展开,是一个二维数组(每一行是一个磁道)
- 把整个磁盘的所有柱面展开,是一个三维数组(每一层是一个柱面)
- 又因为,三维数组在物理存储中,本质上是连续(线性)存储的(约等于还是一位数组存储),所以我们可以直接用数组下标来得到某一扇区的地址,即:LBA地址
- OS使用 LBA地址,交给磁盘以后,磁盘自动把LBA 转换成CHS地址然后搜索对应扇区
二,文件系统
我们想要在硬盘上储⽂件,必须先把硬盘格式化为某种格式的文件系统,才能存储文件。文件系统的⽬的就是组织和管理硬盘中的文件
1. 文件系统基本概念
块:
- 磁盘是"块"设备
- OS在读取磁盘文件的时候,会一次性读取多个扇区(因为磁盘太慢了),即:一个"块"
- ⼀个"块"的大小是由格式化的时候确定的,常见的是4KB为一块
分区:
- 我们将一个盘,进行分区。把管理一个盘变成 → 管理多个区,区与区之间又可以用相同的管理方法
- 同样,分区又被分成组(分区和分组的方式,也是通过记录起始位置和结束位置来划分,每个组的大小一样)

inode(索引节点):
- 用于存储文件的元数据信息,包括指向文件对应的数据块的指针
- 通过 inode,系统可以快速获取文件的属性信息,而无需扫描整个文件系统来查找文件的相关信息
- 文件名不存储在inode中 ,但是
inode
会存储inode_number
来标识文件 inode_number
可以跨组编号,但是不能跨区编号。即:一个组内不能出现同一个编号(一个区内编号唯一),但是不同区内可以出现同一编号- 每个文件的基本属性项是相同的(如,都有
type
,size
...),对应的值不同。所以每个struct inode
的大小是一样的
2. ext2 文件系统
只要我们管理好一个组,就相当于管理好了一片区,就相当于管理好了一个盘。所以下面我们对每个组的结构进行了解
块组内部构成
Data Blocks
- 数据区:存放文件内容
- 一个文件通过
inode
里的指针可以找到对应的数据块 - 如果一个文件过大,一个块(4KB)存不下,可以建立多级索引表,即块中存储指向别的块的指针,从而增大容量(并且可以跨组,但是不能跨区)
- Block 号按照分区划分,不可跨分区

inode table
- 用来存储该组内,所有文件的
inode
信息 inode table
如果一块(4KB)不够用,也可以建立多级索引表- inode编号以分区为单位,整体划分,不可跨分区
Block / inode Bitmap
- Block Bitmap:记录着 Data Block 中哪个数据块已经被占用,哪个数据块没有被占用
- inode Bitmap:每个 bit 表示⼀个 inode 是否空闲可用
- 文件的删除操作,无序删除data block里面数据块的内容,只需要改变block bitmap 和 inode bitmap 1 → 0就行,代表可用,下次就会覆盖写了。(格式化就是全置 0 了)
GDT
- 块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符
- 每个块组描述符存储⼀个块组 的描述信息,如在这个块组中从哪里开始是inode Table,从哪⾥开始是DataBlocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有⼀份拷贝
Super Block
- 存放⽂件系统本⾝的结构信息,描述整个分区的文件系统信息
- 不是所有的group里面都有super block,部分有,且这些super block的内容都一样
- 为什么存多份?用于备份(因为super block是用来描述整个分区的,如果损坏了,那整个分区就乱了)
操作系统开机时,就会把磁盘的管理信息super block
加载到内存里。而GDT
、Block Bitmap
、inode Bitmap
(是按需加载)
3. 理解一
我们捋一遍访问的过程:
当我们拿到文件inode_number
的时候,就可以到对应的块组的inode table
里面找到对应的struct inode
,然后通过struct inode
可以知道文件对应的属性,以及有了指向数据块的指针,也可以拿到数据。这时候就成功访问了对应的文件。
但是inode_number
怎么得到呢?通过目录。
4. 目录与文件名及路径解析
- 在Linux中,目录也是文件
- 目录的内容,存储的就是当前目录下,普通文件的文件名和它的
inode_number
的映射关系 - 我们访问一个文件的时候必须带路径(绝对 / 相对 / 默认):
- 我们直接使用文件名:本质还是用的当前路径 + 文件名
- 因为如果要找到一个文件的
inode_number
必须到上层目录的内容里面查找映射关系 - 所以我们要访问任何一个文件,都需要从根目录开始,层层解析 ,直到在我们要访问的文件的目录里找到
inode_number
(这就是Linux路径解析)
- 根目录是在开机的时候就自动打开的
一条命令ls code.c
,路径都是由谁提供的?
ls
的路径由系统提供:进程通过env找到PTAH默认路径code.c
的命令用户提供:即当前的相对路径
5. 路径缓存
访问任何⽂件,都要从/
目录开始重新进行路径解析吗?
答:
- 不是
- 因为这样太慢。每次在目录里面找映射关系,也是对磁盘的IO,访问外设太慢。
- 所以,Linux会缓存历史路径结构(用
dentry
树,用于维护树状路径结构)。
dentry
树(内存数据结构):
- 每个文件名(普通文件和目录)对应一个
dentry
,dentry
在struct file
里,dentry
里面存储了指向对应文件inode
的指针 - 这些
struct dentry
会被系统用一颗树组织起来 dentry
节点同时也会属于LRU
(最近最少使⽤)结构中,用于淘汰。会属于Hash
结构,方便快速查找dentry
树,整体构成了Linux的路径缓存结构。- 访问任何⽂件,都在先在
dentry
树下根据路径进行查找,找到了就可以通过里面的指针找到对应的inode
- 没找到就从磁盘加载路径,添加
dentry
结构,缓存新路径
- 访问任何⽂件,都在先在
6. 挂载分区
我可以用inode_number
的在一个分区内找到对应文件的inode
,但是我们怎么知道它属于哪个分区呢?
- 分区写入文件系统,无法直接使用,需要和指定的目录关联,进行挂载才能被用户访问。
- 通过挂载点,我们就可以知道这个文件属于哪个分区(即:可以根据访问⽬标⽂件的 路径前缀 准确判断我在哪⼀个分区。)
- 如:将
/dev/sda1
挂载到/mnt/data
mount /dev/sda1 /mnt/data
- 挂载后,访问
/mnt/data
目录实际上就是访问/dev/sda1
分区的内容,我们就知道是哪个分区了
7. 总结
图片来自:极客时间趣谈操作系统
三,软硬链接
1. 软链接
- 软连接是创建了独立的文件
- 语法:
cpp
ln -s [源文件或目录] [目标软链接文件或目录]
- 例如,要为当前目录下的
file.txt
文件创建一个名为file_link.txt
的软链接
cpp
ln -s file.txt file_link.txt
- 建立好以后,运行
file_link.txt
== 运行file.txt
(相当于file_link.txt
是file.txt
的快捷方式)
示例:
当前目录下建立软链接:
建立一个软链接在上级目录:
- 路径一定要写清楚
- 如果链接成:
b.exe -> a.exe
,则你在b.exe
的目录下运行b.exe
的时候,也是去当前目录下找a.exe
的
2. 硬链接
语法:
cpp
ln [源文件或目录] [目标软链接文件或目录]
- 硬链接不是独立的文件,硬链接只是⽂件名和目标文件
inode
的映射关系 .
和..
就是硬链接- 硬链接可以用于文件备份
- 但是,用户不能给目录进行硬链接,只有Linux系统可以(如
.
和..
,因为怕用户乱链接,形成文件呢路径环问题)
示例:

ls -li
:可以查文件inode_number
- 可见,
a.exe
,文件权限后面的数字为2
,代表硬链接数为2
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!