最近看到一个问题,引发了这个想法。无法在这里或通过谷歌机器找到答案。基本上,我有兴趣了解内核 I/O 架构是如何分层的。例如,是kjournald
派遣到pdflush
还是相反?我的假设是pdflush
(对海量存储 I/O 更通用)将位于较低级别并触发 SCSI/ATA/实际执行写入所需的任何命令,并kjournald
在写入之前处理更高级别的文件系统数据结构。不过,我也可以反过来看,直接kjournald
与文件系统数据结构交互,并pdflush
时不时地醒来,通过kjournald
.也有可能由于其他原因,两者根本不互动。
基本上:我需要某种方法来可视化(图形或只是解释)用于将 I/O 分派到 Linux 内核中的大容量存储的基本架构。
答案1
pdflush
在我们讨论有关kswapd`的细节之前kjournald, and
,让我们首先了解一下我们正在讨论的 Linux 内核的背景知识。
GNU/Linux 架构
GNU/Linux 的架构可以被认为是两个空间:
- 用户
- 核心
在。。之间用户空间和内核空间GNU C 库位于 ( glibc
)。这提供了将内核连接到用户空间应用程序的系统调用接口。
内核空间可以进一步细分为3个级别:
- 系统调用接口
- 架构独立的内核代码
- 架构相关代码
系统调用接口顾名思义,提供glibc
与内核之间的接口。这架构独立的内核代码由VFS(虚拟文件系统)和VMM(虚拟内存管理)等逻辑单元组成。这架构相关代码是给定硬件架构的处理器和平台特定代码的组件。
GNU/Linux 架构图
在本文的其余部分中,我们将重点关注内核空间中的 VFS 和 VMM 逻辑单元。
GNU/Linux 内核的子系统
VFS子系统
有了 GNU/Linux 内核如何构造的高级概念,我们就可以更深入地研究 VFS 子系统。该组件负责提供对各种块存储设备的访问,这些设备最终映射到物理设备(HDD/等)上的文件系统(ext3/ext4/等)。
VFS示意图
此图显示了write()
用户进程如何遍历 VFS 并最终向下到达设备驱动程序,并在设备驱动程序中将其写入物理存储介质。这是我们第一次相遇的地方pdflush
。这是一个守护进程,负责在后台将脏数据和元数据缓冲区块刷新到存储介质。该图没有显示这一点,但还有另一个守护进程 ,kjournald
它位于旁边pdflush
,执行类似的任务,将脏日志块写入磁盘。笔记:日志块是 ext4 和 JFS 等文件系统在文件发生更改之前跟踪磁盘更改的方式。
上述细节将在进一步讨论这张纸。
write()
步骤概述
为了提供 I/O sybsystem 操作的简单概述,我们将使用一个write()
由用户空间应用程序调用该函数的示例。
- 进程通过
write()
系统调用请求写入文件。 - 内核更新映射到文件的页面缓存。
- pdflush 内核线程负责将页面缓存刷新到磁盘。
- 文件系统层将每个块缓冲区放在一起到一个
bio struct
(请参阅第 23 页上的 1.4.3,“块层”)并向块设备层提交写请求。 - 块设备层从上层获取请求并执行I/O电梯操作并将请求放入I/O请求队列。
- 设备驱动程序(例如 SCSI 或其他设备特定驱动程序)将负责写入操作。
- 磁盘设备固件执行硬件操作,例如寻道头、旋转以及将数据传输到盘片上的扇区。
VMM子系统
继续深入研究,我们现在可以研究 VMM 子系统。该组件负责维护主内存 (RAM)、交换区和物理存储介质之间的一致性。保持一致性的主要机制是bdflush
。由于内存页被视为脏页,因此它们需要与存储介质上的数据同步。bdflush
将与pdflush
守护进程协调将此数据与存储介质同步。
VMM示意图
交换
当系统内存变得稀缺或内核交换计时器到期时,kswapd
守护进程将尝试释放页面。只要空闲页面数保持在以上free_pages_high
,kswapd
就不会做任何事情。但是,如果空闲页面数下降到以下,kswapd
则将启动页面回收过程。kswapd
将页面标记为要重定位后,bdflush
将注意通过pdflush
守护程序将任何未完成的更改同步到存储介质。