Linux---磁盘与文件系统(三)

问:我们如何理解创建,删除,修改,查找?(这些场景都是先从文件的 inode 编号开始的)

• 创建:在 inode bitmap 中找到空闲 inode 编号 → 初始化 inode 元数据(权限、UID、GID、时间戳等)→ 分配数据块并写入内容,更新 inode 指针 → 在父目录中建立"文件名 → inode 编号"的映射。

• 删除:根据 inode 编号找到对应 inode → 链接计数减 1,若计数为 0 且无进程打开,则释放数据块(block bitmap 标记空闲)和 inode(inode bitmap 标记空闲)→ 从父目录中删除"文件名 → inode 编号"的映射。

• 修改:根据 inode 编号定位 inode → 修改内容时,分配新数据块、更新 inode 指针与文件大小,并更新修改时间(mtime);修改属性时,直接更新 inode 元数据(权限、所有者等),并更新属性修改时间(ctime)。

• 查找:从根目录开始,逐层解析路径,在每个目录的数据块中通过文件名找到对应 inode 编号 → 根据 inode 编号定位 inode → 读取文件数据或元数据。

文件删除是否删干净说明:

Linux Ext文件系统的普通删除操作,并不是真正把文件数据从磁盘上清除,只是将inode bitmap和block bitmap中对应的位置标记为空闲状态,同时删除文件名与inode的映射关系。数据块中原有的文件内容依然保留在磁盘上,只有后续写入新数据时发生覆盖,原有数据才会真正消失。因此普通删除操作并没有彻底删干净,这也是数据可以被部分恢复的原因。

目录和文件名

我们用的一直都是文件名!!!文件名不在inode内部保存,而是保存在目录文件的"目录项表中"

如何理解目录?

答:在Linux下,一切皆文件,目录也是文件,文件=内容+属性,目录本身也有自己的inode和数据块,当你访问一个文件路径(如/home/user/file.txt)时,系统会从根目录开始,逐层读取目录文件中的目录项表,通过文件名找到对应的inode编号,最终定位到文件。

在磁盘和文件系统角度,存储目录和存储普通文件是没有任何区别的。

目录内容保存的是当前目录下所有文件和子目录的"文件名->inode编号"的映射关系(即目录项表)

目录的属性:由它自己的inode来描述,包括权限、所有者,大小,时间戳等

文件名的位置:文件名并不保存在文件自身的inode里面,而是保存在包含它的目录文件里面。

这也解释了为什么:一个文件可以有多个文件名(硬连接),因为多个目录项可以指向同一个inode;删除文件时,只是删除了目录项和inode的映射,而不是直接删除inode本身。

重命名文件时,只需要修改目录项的文件名,而不需要修改inode或数据块。

重谈inode编号和块号

inode编号和块号:不是块组内有效,整个分区内都有效。不能跨分区。

在一个分区内部,一个文件系统内部,有多少inode,有多少数据块,都是固定的,都是提前设计好的。

问题:如果我要访问我的当前文件内容或者属性,首先要做的是打开当前目录,访问当前目录的数据块,首先需不需要首先找到当前目录的inode?

答:需要,任何文件或目录的访问都必须先找到对应的inode,目录本身也是一种特殊的文件,它的inode中存储了该目录的元数据,(比如权限、大小、数据块指针等),而目录的数据块中则存储了该目录下的文件/子目录名称与对应inode号的映射关系。

要访问当前目录的内容和属性,流程是:1、先找到当前目录的inode获取他的数据块指针

2、再通过数据块指针读取目录的数据块,才能获取其中的文件/子目录信息。

路径解析

#路径解析(Path Resolution)简明概念 路径解析:把 "相对路径 / 模糊路径",转换成"唯一、确定、可直接使用的绝对路径"的过程。

  1. 核心作用 - 把 `./a.txt`、`../dir`、`~` 这类"简写路径" - 变成系统能直接定位文件的"完整绝对路径"(如 `/home/user/file/a.txt`)

  2. 解析时主要做这几件事

  3. 处理当前目录 `.`。 `.` 表示当前所在目录,直接保留或替换。

  4. "处理上级目录 `..`" 每遇到一个 `..`,就**往上退一级目录**。

3."处理多余斜杠" 把 `//`、`///` 统一成 `/`。

  1. **展开符号链接(软链接)** 找到链接真正指向的文件/目录。

  2. **从相对路径算出绝对路径** 结合**当前工作目录**,算出完整路径。 ---

  3. 简单例子 当前目录:`/home/user` - 输入:`../doc/./note.txt` - 解析后:`/home/doc/note.txt` ---

  4. 常见场景 - Linux / Windows 文件系统路径 - 命令行 `cd`、`ls` 等命令内部 - 编程语言:`os.path.abspath()`、`path.resolve()` - 网页 URL 路径解析 ---

一句话总结: 路径解析 = 把"简写路径"翻译成系统能看懂的"唯一绝对路径"。

路径缓存

问题1:Linux磁盘上,存在真正的目录吗?

答:不存在,只有文件,在Linux的文件系统设计里,目录本质是一种特殊的文件,它不会存储普通文件的内容,仅保存文件的属性(比如inode编号,权限等)和文件/子目录的名称映射关系。

问题2:访问任何文件都是要从目录开始进行路径解析吗?

答:原则上来说是要从根目录开始解析,但是这样的方式效率较低,Linux会引入路径缓存(也叫目录项缓存),将历史访问过的路径结构缓存起来,后续访问相同或相关路径时,可以直接从缓存中读取信息,避免重复解析,提升访问速度。

问题3:Linux的目录概念是怎么产生的?

答:目录的概念是由操作系统在内存中维护的。当打开的文件时目录类型时,操作系统会在内存中构建并维护该目录对应的路径结构,而路径缓存即使操作系统在内存中维护目录结构的核心机制之一,它通过缓存目录项来模拟出"目录"的逻辑概念,方便用户和程序组织、查找文件。

路径缓存(也叫目录项缓存,dentry cache)是Linux内核为提升文件路径解析效率而设计的内存缓存机制。

它的核心逻辑是:当系统首次解析文件路径时,会从根目录开始逐层查找对应的目录和文件,并将解析过程中产生的目录项(dentry)、文件的inode映射关系等信息保存在内存缓存中。后续再次访问相同或相关路径时,系统可以直接从路径缓存中读取已有的解析结果,无需从根目录重新逐层解析,从而大幅减少路径解析的时间开销,提升文件访问速度。

简单来说,路径缓存就是Linux系统为了避免重复"找路"而建立的"路径记忆库"。

路径缓存的概念

路径缓存(目录项缓存)是Linux内核为加速文件路径解析而设计的内存缓存机制,它缓存已解析的路径信息,避免重复解析,提升文件访问效率。

问题:这颗多叉树会动态变化吗?

1、这颗路径缓存多叉树,是会动态变化的,当系统中新建、删除、重命名文件或目录时,内核会在dentry cache中对应的节点进行添加、删除、或者修改操作。

2、当某个dentry长时间没有被访问,内核会将其从缓存中淘汰(回收内存),对应的节点会从多叉树中移除。

3、当访问一个未被缓存的路径时,内核会从磁盘读取目录结构并且在dentry cache中创建新的节点,多叉树也会新增对应的节点。

问题:只有目录才会有dentry吗?

不是,不仅目录有dentry,普通文件、符号链接、设备文件等所有的文件系统对象都有对应的dentry。dentry是文件名和inode之间的映射,只要是文件系统中能被命名的对象,都会有对应的dentry。

每一个被访问的文件都有dentry,包括普通文件,(叶子节点)

注意:不是每一个路径都有dentry

只有被访问过,被缓存的路径,才会有dentry

搜索的时候,可能第一次比较卡顿,第二次就快了!路上路径被缓存了。

举例:

--- 路径:/home/user/test.txt

  1. 从根目录 / 开始,找到根 dentry

  2. 在根 dentry 下查找 home,得到 home 的 dentry

  3. 在 home dentry 下查找 user,得到 user 的 dentry

  4. 在 user dentry 下查找 test.txt,得到 test.txt 的 dentry

  5. 通过 test.txt 的 dentry 找到对应的 inode

  6. 最终找到文件数据

核心解析过程(路径:/home/user/test.txt)

  1. 从根目录 / 开始,找到内核预先创建的根 dentry(关联根 inode,ext4 中通常为 2)

  2. 在根 dentry 下查找 "home":缓存中有则直接取,无则读磁盘创建 home dentry 并加入 dcache 3. 在 home dentry 下查找 "user":优先查 dcache,找到后关联 user 的 inode

  3. 在 user dentry 下查找 "test.txt":找到对应的 dentry 并关联其 inode

  4. 通过 test.txt 的 inode 定位文件实际数据块,完成路径解析

关键注意事项

  1. dentry 仅记录「路径名 ↔ inode」映射和目录层级关系,不存储文件实际数据

  2. dcache(dentry 缓存)是性能核心:重复访问同一路径时,直接用缓存的 dentry,无需读磁盘 3. 执行 rm /home/user/test.txt 后:test.txt 的 dentry 会被标记为无效,解除与 user dentry 的关联 4. 失效的 dentry 不会立即删除,内存紧张时由内核自动回收 5. 再次解析已删除的 test.txt 路径,内核会返回「文件不存在(ENOENT)」错误

访问任何文件,都是要先做路径解析和路径缓存的!!!

那么问题来了,路径是谁提供的?

访问文件时,路径的核心提供者(按优先级/场景分类)

  1. 核心来源:用户/开发者(最根本) - 手动操作:你在终端输入 `cat /a/b.txt`、双击桌面文件,路径由你直接指定 - 程序开发:代码中写 `open("./config.ini")`、`os.path.exists("/var/log.log")`,路径由开发者编码定义

  2. 传递/中转者:应用程序/系统组件 - shell(bash/zsh):接收你输入的路径,传递给内核(如 execve 系统调用) - 应用程序:浏览器打开下载文件、编辑器打开工程文件,路径由程序根据你的操作拼接/读取 - 系统服务:crontab 执行脚本、日志服务写文件,路径由服务配置文件(开发者/管理员配置)提供

  3. 特殊场景的补充提供者: - 相对路径基准:`../test.txt` 的完整路径 = 进程当前工作目录(PWD,进程自身属性) + 相对路径

  • 环境变量:`$HOME/test.txt` 的路径 = 系统/用户配置的环境变量值 + 后缀路径

  • 软链接/挂载:访问 `link.txt`(软链接)时,真实路径由软链接文件内容提供;访问挂载目录路径由挂载配置提供

  • 默认路径:程序未指定路径时,用系统默认路径(如 `/tmp`),由程序/系统预设

关键结论 - 无论哪种场景,路径的「原始字符串」最终都来自**用户输入、开发者编码、系统/程序配置**; - 内核只负责「接收路径字符串」并做解析/缓存,不生成路径,仅处理路径。

存储大文件问题

当文件超过12个直接块能覆盖的大小时(48kb)时,inode就会启用多级间接索引来管理大文件。

大概流程:假如要访问一个1GB的文件

1、内核先看inode的直接块,发现不够,去查一级间接块。

2、一级间接块也不够,再查二级间接块。

3、在二级间接块的索引表里,找到对应数据块的指针,再去读数据

4、访问路径变长,磁盘I/O次数变多,所以大文件的访问速度会比小文件慢一些。

问题:如何判断文件在哪一个文件系统中?

挂载

磁盘->分区->格式化

1、格式化的本质是在输入管理信息。磁盘级文件系统。

2、分区格式化之后,这个文件系统或者分区,能不能直接被使用?

答:不能。需要把分区或文件系统挂载到指定的目录下。

分区写入文件系统,无法直接使用,需要和指定的目录关联,进行挂载才能使用。

挂载 = 将一个文件系统,接入到目录树的某个目录。 让该目录成为访问这个文件系统的入口。

相关推荐
deng-c-f2 小时前
Linux C/C++ 学习日记(80):Kafka(八):topic会自动创建吗?
linux·c++·学习·karfka
低保和光头哪个先来2 小时前
TinyEditor 篇3:拖拽图片到编辑器并同步上传至服务器
运维·服务器·编辑器
rain_in_spring2 小时前
十、项目:营销中心
linux·运维·服务器
小杍随笔2 小时前
【Rust `lib.rs` 使用方法:模块组织、API导出与最佳实践】
服务器·开发语言·rust
csdn_life182 小时前
# Debian 10 升级到 Debian 13 指南
运维·debian·php
U盘失踪了2 小时前
Debian 使用 Xfce 桌面
linux·运维
k7Cx7e2 小时前
Debian安装 curl 时提示插入 DVD 光盘
运维·windows·debian
云飞云共享云桌面2 小时前
广东某智能装备工厂8人共享一台服务器
大数据·运维·服务器·人工智能·3d·自动化·电脑
鹓于2 小时前
OmniParser视觉鼠标自动化实战
运维·自动化·计算机外设