文件系统与存储栈
这页讲的是:程序眼里的“文件”和磁盘眼里的“块设备”并不是一回事,Linux 需要一整套分层结构,才能把读写请求从文件名一路落到具体存储介质上。学这页的关键,是把“文件语义”和“块 I/O 路径”这两个层次分开看。
这块是什么
文件系统与存储栈负责组织“数据如何被命名、访问、缓存、落盘”。对应用来说,它表现为路径、目录、文件、权限;对底层设备来说,它又要面对块设备、请求队列、I/O 调度和介质差异。你看到的是“打开一个文件”,内核看到的却是一条跨越多个层次的完整路径。
可以把它看成两层:上层讲“文件是什么”,下层讲“这些数据最终怎么写到存储设备上”。
它负责什么
提供文件抽象
- 路径、目录、文件、权限
- 统一 open/read/write 这类接口
- 隐藏不同文件系统差异
- 让应用不需要按设备细节来思考数据访问
组织具体文件系统
- ext4、xfs 等具体实现
- 元数据管理
- 一致性与恢复
- 把“文件语义”真正落到磁盘组织方式上
连接块层与存储设备
- 把 I/O 请求下发到设备
- 处理缓存和写回
- 适配不同存储介质
- 让上层不必直接面对设备读写细节
一条文件读写路径大致长什么样
| 阶段 | 你现在怎么理解 | 背后的关键点 |
|---|
| 路径解析 | 内核先根据路径找到对应目录项和文件对象。 | 这一步和 dentry、inode 这类核心对象相关。 |
| 文件语义处理 | 检查权限、偏移、打开方式等语义问题。 | 说明“读文件”不只是把字节拿出来,还要遵守文件模型规则。 |
| 缓存命中或缺失 | 数据可能已经在页缓存里,也可能需要进一步访问设备。 | 这解释了为什么文件 I/O 和内存管理关系很深。 |
| 块 I/O 下发 | 如果必须落到设备层,就要通过块层组织成真正的 I/O 请求。 | 说明“文件系统”和“磁盘驱动”之间并不是直接连在一起的。 |
关键概念
| 概念 | 现在怎么理解 |
|---|
| VFS | 虚拟文件系统层,给上层提供统一文件接口,让不同具体文件系统看起来更一致。 |
| inode | 文件的核心元数据对象,记录权限、大小、位置等信息。 |
| dentry | 目录项,负责把“名字”与文件对象关联起来。 |
| 页缓存 | 文件数据经常先在内存里缓存,不一定每次都直接打磁盘。 |
| 块层 | 负责把上层 I/O 组织成设备能处理的请求。 |
为什么重要
- 应用几乎每天都在通过文件接口访问数据,这是最核心的系统能力之一。
- 很多性能体验,不只取决于磁盘快慢,还取决于缓存、写回和 I/O 路径设计。
- 文件系统经常是“用户感知最强”的内核模块之一,因为数据可靠性直接关系到系统可信度。
- 很多“明明只是读写文件”的问题,往下追会同时碰到 VFS、页缓存、块层和设备驱动。
常见误解
- 误解一:文件系统就是磁盘。实际上文件语义层和块设备层是不同层次。
- 误解二:读文件一定会去读盘。实际上很多读取会先命中页缓存。
- 误解三:块层只是驱动细节。实际上它是上层文件 I/O 和底层设备之间的重要组织层。
它不负责什么
- 它不决定谁运行,那是调度器的职责。
- 它不直接管理物理内存整体布局,但高度依赖页缓存和内存回收。
- 它不负责网络协议,不过远程存储和网络文件系统会跨到网络子系统。
和其他模块的关系
| 相关模块 | 关系 |
|---|
| 内存管理 | 页缓存、回收、写回都与内存管理深度耦合。 |
| 驱动 | 块设备驱动和控制器驱动承接实际硬件读写。 |
| 并发控制 | 目录项缓存、inode 状态、写回流程都有并发同步问题。 |
| 网络 | NFS、SMB 等远程文件系统把文件语义扩展到网络之上。 |
最容易混的几层现在怎么拆
| 层次 | 它在管什么 | 不要和谁混 |
|---|
| VFS / 文件语义层 | 统一路径、目录、文件对象和权限这些“文件世界规则”。 | 别把它和具体磁盘格式或驱动当成一回事。 |
| 具体文件系统 | 把抽象文件语义真正落成 ext4、xfs 这类具体磁盘组织方式。 | 别把它和块层的请求组织混成一层。 |
| 页缓存与写回 | 决定数据先在内存里怎样缓存、什么时候再推回存储。 | 别把“读文件”简单理解成“立刻读盘”。 |
| 块层与设备路径 | 把上层 I/O 意图组织成底层设备真正能执行的请求。 | 别把文件名世界和设备请求世界硬连成一条直线。 |
读完这页后,你应该能回答
- 为什么“文件系统”和“磁盘驱动”不是一个层次的问题?
- 为什么页缓存会让文件系统和内存管理深度绑在一起?
- 为什么一个简单的文件读写请求,背后会跨越多层结构?
后面适合继续问:VFS 为什么重要?页缓存到底算内存还是文件系统的一部分?块层和具体文件系统怎么配合?