Linux学习笔记(十三)--文件系统

文件系统概念

Linux文件系统是操作系统用于管理存储设备(如硬盘、SSD、U盘等)上数据存储和组织的核心组件,它定义了文件的命名、存储、检索、更新以及权限控制等规则。

理解文件系统

当我们使用ls -l会看到

复制代码
ls -l

我们会看到每行包含七列:模式;软硬链接数;文件所有者;组;大小;文件最后修改时间;文件名

认识磁盘

磁盘是电脑上唯一一个机械设备,也是一个外设。

磁盘的组成

磁盘主要由盘片,磁道,扇区,读写头,磁头臂和主轴这些部分组成。它们的作用分别是:

盘片:数据存储的物理介质

读写头:数据的读取和写入

磁头臂:定位磁头到指定磁道

主轴:驱动盘片高速旋转

磁道:数据存储的基本环形单元

扇区:最小的可寻址存储单元

磁盘访问的最基本单元是扇区,通常为512字节或4kb。

磁盘寻址方式

我们可以把磁盘看做由无数个扇区构成的存储介质。要把数据存储到磁盘中,首先要定位到扇区,哪一面,哪一个磁头->哪一个磁道->哪一个扇区。磁头在磁盘高速旋转时左右摆动本质是定位磁道和扇区的过程。

CHS寻址方式

CHS是传统的磁盘物理寻址方式,它通过三维坐标来精确定位磁盘上的每一个扇区。

三维寻址结构
复制代码
CHS 坐标:(柱面号, 磁头号, 扇区号)
    ↓
磁盘物理位置
寻址过程
复制代码
主机请求:CHS = (120, 2, 5)
    ↓
1. 磁头臂移动到第120柱面(寻道)
2. 选择第2号磁头(激活对应盘面的磁头)
3. 等待盘片旋转到第5扇区
4. 读取/写入数据

每个磁盘都有固定的CHS参数如:最大柱面数(C)的典型值1024,最大磁头数(H)的典型值255(受限于8位),最大扇区数(S)的典型值63

寄存器

类别

寄存器按功能可分为四大核心类别:控制寄存器、数据寄存器、地址寄存器、状态寄存器。每类寄存器都有特定的功能和用途,共同协作完成CPU的各种任务。

控制寄存器:用于存储控制信息,控制CPU的操作模式和功能。例如,程序状态字(PSW)中的标志位、中断允许位、工作模式位等都属于控制寄存器。

数据寄存器:用于暂存参与运算的数据,是CPU与内存之间数据交换的缓冲器。在运算过程中,数据从内存读取到数据寄存器,经过ALU运算后结果再写回数据寄存器。

地址寄存器:用于存放内存地址,指示CPU要访问的内存单元位置。如程序计数器(PC)存放下一条指令地址,基址寄存器、变址寄存器等用于形成有效地址。

状态寄存器:用于记录CPU执行指令后的状态信息,如进位标志(CF)、零标志(ZF)、溢出标志(OF)等。这些标志位会影响后续的条件转移指令执行。

CPU通过寄存器与磁盘(I/O设备)进行数据和控制交互

核心机制:CPU并非直接操作磁盘数据,而是通过读写磁盘控制器上的一组寄存器来下达命令、传递参数并获取状态。

寄存器功能分工:

控制寄存器:CPU通过向其中写入命令(如r/w,即读/写)来控制磁盘启动某项操作。

地址寄存器:CPU向其中写入要访问的数据位置。

数据寄存器:作为数据传输的缓冲区。写操作时,CPU将待写入的数据放入此寄存器;读操作时,CPU从此寄存器读取磁盘准备好的数据。

状态寄存器:磁盘将操作结果和当前状态(如是否忙、是否出错)写入此寄存器,供CPU读取判断。

文件系统的基本功能

数据组织:将存储设备划分为固定大小的块(如4KB),并通过元数据(如inode)记录文件属性(权限、大小、位置等)。

命名空间:提供树形目录结构(以/为根),支持文件/目录的层次化命名。

访问控制:通过权限位(rwx)、ACL(访问控制列表)限制用户对文件的访问。

数据持久化:确保文件在系统重启后仍可访问,并通过日志等机制保证崩溃一致性。

inode

上图为磁盘文件系统图

boot block:(管理操作系统启动的相关信息)在每个分区的头部,将剩下的部分划分成n个block group。

Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相 同的结构组成。政府管理各区的例子

超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量, 未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的 时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个 文件系统结构就被破坏了

GDT,Group Descriptor Table:块组描述符,描述块组属性信息(它是这个块组的"详细目录"。它记录了本块组内其他各个部分(位图、inode表、数据块区域)的起始块和状态信息。操作系统通过它快速定位到本块组的管理数据。)

块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没 有被占用(它本质上是一个巨大的二进制(0/1)地图,每一位(bit)对应本块组内的一个数据块。0表示这个数据块是空闲的。1表示这个数据块已被占用。)

inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。

i节点表:存放文件属性 如 文件大小,所有者,最近修改时间等

数据区:存放文件内容

核心定义:inode 是文件系统中用于存储文件元数据的数据结构。它不包含文件的内容,而是包含文件的属性。

inode存储的关键信息:

#define NUM 15:这是一个宏定义,表明后续的 blocks数组大小为 15。这里的数字 15 是一个简化的例子。在实际的经典文件系统(如 ext2)设计中,inode 中用于存储数据块指针的数组通常有 12 个直接指针、1 个一级间接指针、1 个二级间接指针和 1 个三级间接指针,总共 15 个"槽位"。这能支持从几 KB 到 TB 级别的文件大小。

inode number:这个字段存储 inode 的编号。它是 inode 在文件系统中的唯一标识,类似于身份证号。内核通过这个编号在磁盘的 inode 表中定位具体的 inode。

文件类型:用于标识这个 inode 代表的是普通文件、目录、符号链接、设备文件(字符/块设备)、管道还是套接字等。

权限:存储经典的 Unix 文件权限位,即 rwxrwxrwx(所有者、组用户、其他用户的读、写、执行权限)。

引用计数:这是一个极其关键的字段。它记录了这个 inode 当前被多少个目录项(即硬链接)引用。只有当引用计数降为 0 时,系统才会真正释放这个 inode 及其占用的数据块。这正是硬链接的工作原理。

拥有者与 所属组:通常存储用户的 UID 和组的 GID,用于进行文件访问权限的归属判断。

ACM时间:这是三个时间戳的合称,通常包括:A-time (Access Time): 最后一次访问文件内容的时间(如 cat, less)。C-time (Change Time): 最后一次更改文件inode元数据的时间(如修改权限、重命名)。M-time (Modify Time): 最后一次修改文件内容的时间。

int blocks[NUM]:这是 inode 的核心数据。这个数组存储了文件内容所在的物理磁盘块号。

其工作方式是一个多级索引结构(以经典的 ext2 为例,这也是为什么 NUM=15 的常见原因):

blocks[0]到 blocks[11]:直接指针。它们直接指向文件的前 12 个数据块。对于小文件(如 ≤ 48KB,假设块大小为 4KB),这就足够了。

blocks[12]:一级间接指针。它指向一个数据块,但这个数据块不存文件数据,而是存满了更多指向数据块的指针。这可以寻址更多的数据块。

blocks[13]:二级间接指针。它指向一个块,这个块里存的指针,每个又指向一个块,那些块里存的才是最终的数据块指针。这形成了两级索引。

blocks[14]:三级间接指针。原理同上,形成三级索引,可以支持非常大的文件。

文件系统的工作流

创建文件:

(1)系统先在 inode 位图​ 中找一个空闲位,标记为占用。

(2)在对应的 inode 表​ 位置初始化一个 inode 结构,填写权限、所有者等信息。

(3)根据文件大小,在 块位图​ 中找若干个空闲数据块,标记为占用。

(4)将找到的数据块编号(指针)填入 inode 的"数据块指针"字段。

(5)最后,在父目录的"目录文件"(它本身也占用数据块)中,添加一条记录:文件名 -> inode编号

读取文件:

(1)从根目录 /的 inode 开始,找到其数据块,在里面找到 home的 inode 编号。

(2)进入 home目录的数据块,找到 user的 inode 编号。

(3)进入 user目录的数据块,找到 hello.txt的 inode 编号(假设是 12345)。

(4)关键步骤:根据编号 12345,定位到它所在的块组和 inode 表​ 中的具体位置。

(5)从该 inode 中读取权限信息(检查你是否能读)和数据块指针。

(6)根据指针,去 Data blocks​ 区域找到对应的数据块,将内容读取出来。

dentry缓存:

dentry 缓存​ 是 Linux 内核维护的一个内存中的数据结构,用于缓存最近使用过的 dentry 对象。

当我们需要查找文件时,直接在缓存中查找,避免读盘。

软硬链接

硬链接

硬链接​ 本质上是在同一个文件系统内,为同一个 inode 创建多个不同的文件名。换句话说,硬链接是指向同一个 inode 的目录条目。

创建命令
复制代码
ln 源文件 硬链接文件名
例:
ln original.txt hardlink.txt
工作原理

当你创建硬链接时,系统并没有创建新的文件内容,也没有创建新的 inode。它只是在另一个目录(或同一目录)下,创建了一个新的目录条目,这个新条目中的 inode 编号​ 和源文件完全相同。inode 结构体中有一个字段叫 "链接计数"。创建硬链接后,这个计数会 +1。

关键特性

(1)无法区分:所有硬链接都是平等的。你无法区分哪个是"原始文件",哪个是"链接"。它们共享同一个 inode,访问任何一个效果都一样。

(2)同步更新:修改任何一个硬链接的内容,其他所有硬链接的内容都会同步改变,因为它们指向的是同一份数据。

(3)删除机制:删除一个硬链接,只是删除了一个指向该 inode 的目录条目,inode 的"链接计数"会 -1。只有当链接计数减到 0 时,inode 和其占用的数据块才会被真正释放。这是硬链接最核心的特性。

(4)限制:

不能跨文件系统:因为 inode 编号只在同一个文件系统内是唯一的。你不能为一个在 /dev/sda1上的文件,在 /dev/sda2上创建硬链接。

不能对目录创建硬链接:这是为了防止目录树中出现循环,导致文件系统工具(如 find, tar)陷入无限循环。只有超级用户可以创建目录的硬链接。

软链接

软链接,也叫符号链接,是一个独立的文件,它有自己的 inode 和数据块。软链接文件的内容很特殊:它只存储了目标文件的路径字符串。

创建命令
复制代码
ln -s 目标文件 软链接文件名
例:
ln -s original.txt softlink.txt
工作原理

(1)当你创建软链接时,系统会创建一个新的文件,分配一个新的 inode 和新的数据块。

(2)这个新文件的内容不是你的文档或代码,而是目标文件的路径(例如 original.txt)。

(3)当你访问软链接时,系统会读取这个路径,然后去查找真正的目标文件。

关键特性

(1)依赖目标文件:软链接只是一个"快捷方式"。如果删除或移动了目标文件,软链接就会"断链",变成一个"悬空链接"。访问它会报错 "No such file or directory"。

(2)独立文件:软链接有自己的 inode、权限和时间戳。它的文件大小就是它存储的路径字符串的长度。

(3)权限特殊:软链接实际访问权限由目标文件决定。

(4)灵活性强:可以跨文件系统:因为它只存路径,所以可以链接到另一个硬盘或网络存储上的文件。可以链接到目录:这是软链接的一个巨大优势,常用于目录的快捷方式。

核心区别

|-------|-----------------|---------------|
| 特性 | 硬链接 | 软链接 |
| 本质 | 同一个 inode 的多个别名 | 一个存储了路径的特殊文件 |
| inode | 相同 | 不同 |
| 跨文件系统 | 不可以 | 可以 |
| 链接目录 | 一般不允许 | 允许 |
| 文件大小 | 与原文件相同 | 等于路径字符串长度 |
| 删除源文件 | 只是链接数减1,数据仍在 | 链接断链,无法访问 |
| 关系 | 如一个人的多个名字 | 如windows的快捷方式 |

页框(页帧)
核心背景

分页机制:

现代操作系统都使用虚拟内存技术。其核心思想是:每个进程都拥有一个独立的、连续的、巨大的虚拟地址空间(例如,32位系统是4GB,64位系统则巨大无比)。然而,物理内存(RAM)是有限的,并且可能不连续。分页机制​ 将虚拟地址空间和物理内存都划分成固定大小的块。虚拟内存中的块称为页,物理内存中的块称为页框。操作系统通过页表​ 来维护虚拟地址空间中的"页"到物理内存中"页框"的映射关系。

定义:页是虚拟内存的基本管理单位。它是进程视角下的内存单元。

特点:(1)存在于虚拟地址空间中。

(2)大小固定,通常为 4KB(在 x86-64 架构下)。现代系统也支持更大的页,如 2MB 或 1GB(称为大页,Huge Pages)。

(3)一个进程的代码、数据、堆、栈等,都被分割成一个个页。

(4)页是逻辑上连续的,但在物理内存中,它们所映射的页框可能是不连续的。

页框(页帧)

定义:页框是物理内存的基本管理单位。它是物理内存被划分成的固定大小的块。

特点:(1)存在于物理内存(RAM)​ 中。

(2)大小与页完全相同(如 4KB),以便一一对应。

(3)页框是物理上连续的内存块。

(4)操作系统内核维护着所有页框的状态(空闲、已分配、脏页等)。

页、页框和页表的关系
工作流程

映射:当进程访问一个虚拟地址(例如,在虚拟页 #1 中)时,CPU 的内存管理单元会查阅该进程的页表。

查找:在页表中找到对应的页表项。页表项中包含了该虚拟页映射到了哪个物理页框(例如页框 8),以及一些控制位(如是否存在、是否可写)。

转换:如果该页的"存在位"为 1,表示它已被加载到物理内存中。MMU 将虚拟地址转换为物理地址:物理地址 = 页框基址 + 页内偏移。

访问内存:CPU 使用这个物理地址去访问物理内存(RAM)中的相应页框。

缺页异常:如果页表项中的"存在位"为 0(如图中的虚拟页 #2),表示该页不在物理内存中。这会触发一个缺页异常。

处理缺页:操作系统接管控制权:从磁盘(交换分区或文件)中加载所需的数据。在物理内存中找到一个空闲的页框。将数据从磁盘读入这个页框。更新页表项,使其指向这个新的页框,并将"存在位"置 1。然后,重新执行之前失败的指令,这次就能成功访问了。

操作系统管理内存

现代操作系统几乎都采用基于分页的虚拟内存机制。这是内存管理的基石。

相关推荐
千寻girling6 小时前
五一劳动节快乐 [特殊字符][特殊字符][特殊字符]
java·c++·git·python·学习·github·php
计算机安禾6 小时前
【Linux从入门到精通】第47篇:SystemTap与eBPF——Linux内核观测的显微镜
java·linux·前端
mifengxing7 小时前
操作系统(四)
linux·服务器·网络·操作系统
钟智强7 小时前
潜伏 9 年的 Linux 核弹级漏洞:CopyFail CVE-2026-31431
linux·数据库·web安全
HUGu RGIN7 小时前
Linux部署Redis集群
linux·运维·redis
先知后行。7 小时前
Linux 内核驱动 —— 锁机制
linux·运维·服务器
技术钱7 小时前
OutputParser输出解析器
linux·服务器·前端·python
波特率1152007 小时前
git指令学习
git·学习
eLIN TECE7 小时前
Golang 构建学习
开发语言·学习·golang
先知后行。8 小时前
Liunx驱动 IO 模型
linux·运维·服务器