40 从意图到I/O:内核如何看待文件、磁盘和设备
# 40 从意图到I/O:内核如何看待文件、磁盘和设备
当进程调用read()时,它请求的不是磁盘,而是数据。接下来的操作并非单一行为,而是内核各层之间的结构化交接,每层都有明确职责。内核看待文件的方式与用户不同,它看到的是结构、委托和执行。从意图到I/O的路径会经过三个核心组件:虚拟文件系统(VFS)、块I/O子系统和设备驱动程序。
VFS是第一个解释用户空间请求的组件,它将路径名简化为内部对象:目录项(dentry)、索引节点(inode)和文件描述符。它无需知道挂载的是哪种文件系统,其作用是提供统一接口并将操作调度到正确的实现。通过抽象和间接,VFS将逻辑访问与物理布局分离。
文件系统驱动程序(如ext4、xfs或其他)将文件偏移量转换为设备上的逻辑块地址,它遍历元数据结构、解析映射并确定请求数据的位置。它不与硬件交互,而是构造一个bio(块I/O向量)结构,该结构从内存页、偏移量和方向的角度描述I/O操作,驱动程序使用submit_bio()提交此结构。
此时,文件上下文已消失。bio层不跟踪用户状态或系统调用来源,仅专注于移动数据:哪些页、哪些扇区、哪个方向。它可能通过多队列(blk-mq)框架合并、拆分或调度bio,将其转换为特定于设备的请求。
栈的末端是设备驱动程序,它不关心请求的触发原因或数据代表什么,其工作是将请求转换为硬件命令:设置DMA、发出操作并处理完成。它执行I/O时对文件、路径或进程一无所知。
I/O栈具有可扩展性,因为每层都坚守自己的角色:VFS解释结构,bio描述I/O,驱动程序执行操作。没有任何一层承担其他层的职责。
设备映射器(Device Mapper)的存在正因这种设计,它干净地适配于bio和驱动程序之间,为加密、镜像或配置提供虚拟块设备,而不触及VFS或文件系统逻辑。它处理bio并传递它们,符合块接口。文件系统在上方不变地运行,驱动程序在下方毫无察觉。由于边界稳固,系统保持一致。
Linux I/O栈经久耐用,因为其各层纪律严明。一次读取从VFS开始,变为bio,并在驱动程序中完成。像设备映射器或回环设备这样的可选层可以拦截或转换请求,而不破坏模型。像eBPF这样的工具可以观察路径而不干扰。
内核看不到文件,它看到的是任务:解析、传输、完成。每一层都恰如其分地做自己该做的事,不多不少,这正是它运作的原因。