kyber-iosched
[toc] block/kyber-iosched.c Kyber I/O调度器 基于延迟目标的现代I/O调度器历史与背景这项技术是为了解决什么特定问题而诞生的?Kyber I/O调度器的诞生是为了解决一个在超高速存储设备(如NVMe SSD)上日益凸显的问题:传统的I/O调度器(如Deadline, CFQ)主要优化吞吐量或公平性,但在现代硬件上,软件排队本身成为了延迟的主要来源。 当存储设备快到可以在微秒级完成I/O时,如果内核软件栈中排队了过多的请求(即高队列深度),那么一个新到来的、关键的读请求可能会排在几百个已提交的请求之后,导致其总延迟变得很高。Kyber的设计目标是转变优化思路:不再间接地追求低延迟,而是直接将延迟作为一个可配置的、必须达成的目标。 它旨在回答这样一个问题:我们如何向设备施加恰到好处的压力,既能获得足够的吞吐量,又能确保绝大多数请求的完成延迟都低于一个预设的目标值? 它的发展经历了哪些重要的里程碑或版本迭代? Facebook (Meta) 的创新:Kyber最初由Facebook的工程...
elevator
[toc] block/elevator.c I/O调度器框架(I/O Scheduler Framework) 可插拔I/O调度的通用层历史与背景这项技术是为了解决什么特定问题而诞生的?block/elevator.c 的诞生是为了解决一个核心的性能问题,并提供一个灵活的解决方案。问题在于:如何高效地组织对机械硬盘(HDD)的I/O请求。 机械硬盘的性能瓶颈在于物理移动:磁头寻道(seek)和盘片旋转(rotation)。无序地处理随机I/O请求会导致磁头在盘片上疯狂来回移动,造成极大的性能浪费。elevator.c 实现的“电梯”(Elevator)框架,其核心目标是: I/O请求排序:像电梯服务楼层一样,先朝一个方向(例如,逻辑块地址LBA递增)处理所有请求,到达末端后再反向,从而将多次随机寻道变为一次或几次大的顺序扫描,最大化吞吐量。 请求合并:将对相邻磁盘区域的小请求合并成一个大请求,减少I/O操作的总次数。 提供可插拔框架:认识到没有一种调度算法能适应所有工作负载(例如,数据库 v...
mq-deadline
[toc] block/mq-deadline.c 多队列截止时间调度器(Multi-Queue Deadline I/O Scheduler) 兼顾吞吐量与延迟的经典算法历史与背景这项技术是为了解决什么特定问题而诞生的?截止时间(Deadline)I/O调度器的诞生是为了解决一个根本性的矛盾:最大化I/O吞吐量与保证请求的公平性和低延迟之间的冲突。 最大化吞吐量:对于机械硬盘(HDD),最高效的方式是处理物理上连续的请求,以最小化昂贵的磁头寻道时间。这意味着应该对请求进行排序和批处理。 保证公平性与低延迟:如果系统只顾着处理连续的大块写操作,那么一个关键的小块读操作(例如,应用程序等待此数据才能继续运行)可能会被“饿死”(starve),等待很长时间才能被服务,导致应用卡顿。 Deadline调度器通过一个优雅的设计来解决这个矛盾:它在默认情况下会合并和排序请求以优化吞吐量,但同时为每个请求设置一个**“截止时间”。如果一个请求在这个时间窗口内没有被服务,它就会被赋予高优先级,强制调度器去处理它,从而防止饥饿并保证了一个可预测的...
blk-core
[toc] block/blk-core.c 块层核心(Block Layer Core) I/O请求的派发与管理中心历史与背景这项技术是为了解决什么特定问题而诞生的?block/blk-core.c 是Linux块层(Block Layer)的绝对核心。它的诞生是为了解决一个根本性的架构问题:如何在种类繁多的上层I/O请求者(文件系统、裸设备访问、交换等)和五花八门的下层块设备驱动(SATA, SCSI, NVMe等)之间建立一个高效、通用、可扩展的中间层。 这个中间层的核心任务包括: 请求抽象与标准化:将来自不同源头的I/O请求(在现代内核中,这些请求被封装在 struct bio 中)转换成一个标准的、可供调度和处理的单元(struct request)。 请求排队与派发 (Queuing & Dispatch):为每个块设备维护一个请求队列(struct request_queue),管理等待处理的I/O请求。 I/O调度 (I/O Scheduling):在将请求发送给硬件之前,通过可...
fops
[TOC] block/fops.c 块设备文件操作(Block Device File Operations) 用户空间直接访问块设备的桥梁历史与背景这项技术是为了解决什么特定问题而诞生的?block/fops.c 的存在是为了实现UNIX哲学的核心思想之一:“一切皆文件”。它专门为了解决一个根本性需求:为用户空间提供一个标准的、基于文件接口的、直接与块设备(如硬盘、SSD)进行底层交互的方式。 在文件系统被创建和挂载之前,操作系统需要一种方法来对原始的块设备本身进行操作。block/fops.c 实现了这个接口,使得以下基础任务成为可能: 分区(Partitioning):工具如 fdisk, parted 需要能够读取和写入磁盘的第一个扇区来管理分区表。 文件系统创建(Formatting):工具如 mkfs.ext4 需要能够直接向一个分区写入文件系统的元数据(超级块、inode表等)。 裸数据传输(Raw Data Transfer):工具如 dd 需要能够进行块级别的、不经过文件系统解释的磁盘克隆或镜像创建。 底层硬件控制(Hardware Cont...
ext4
[toc] fs/ext4/super.c Ext4文件系统核心(Ext4 Filesystem Core) 文件系统的挂载与生命周期管理历史与背景这项技术是为了解决什么特定问题而诞生的?fs/ext4/super.c 是Ext4文件系统驱动的核心,它的诞生是为了解决一个根本性的问题:如何将一个原始的块设备(如硬盘分区)解释并初始化为一个可供操作系统使用的、有组织的文件系统实例。 这个文件中的代码是内核与一个具体Ext4文件系统进行首次“握手”的地方。它负责的任务包括: 引导(Bootstrap):当用户执行 mount 命令时,super.c 中的代码负责从块设备的预定位置读取超级块(Superblock)。超级块是文件系统的“元数据之母”,记录了该文件系统的所有宏观信息(如总大小、块大小、inode数量、魔数等)。 验证与初始化:验证读取到的超级块是否合法(例如,通过检查魔数),并根据其中描述的特性(如是否启用日志、扩展属性等)在内存中建立起管理该文件系统所需的所有数据结构。 生命周期管理:它不仅处理挂载(mount),还负责卸载(unmount)...
mbcache
[toc] fs/mbcache.c 扩展属性块缓存(Extended Attribute Block Cache) 加速文件系统元数据访问历史与背景这项技术是为了解决什么特定问题而诞生的?fs/mbcache.c 实现了一个通用的、基于内存的缓存,其核心目标是加速对存储在独立磁盘块中的文件系统元数据的访问。它专门为**扩展属性(Extended Attributes, xattrs)**的性能优化而设计。 在许多文件系统(如Ext3, Ext4)中,扩展属性(例如,SELinux的安全上下文、POSIX ACLs、用户自定义的元数据)并不总是与文件的inode存储在一起。当一个文件的xattrs过多或过大时,它们会被存储在一个或多个独立的磁盘块中。如果没有缓存,每次需要读取或写入这些xattrs时,文件系统都必须执行一次额外的、独立的磁盘I/O操作。对于元数据密集型的操作(例如,在一个包含大量文件的目录上运行 ls -Z),这会导致显著的性能下降。 mbcache 通过在内存中缓存这些扩展属性块,解决了这个问题。当文件系统需要访问一个xattr块时,它首...
hweight
[toc] include/asm-generic/bitops/const_hweight.hlib/hweight.c软件汉明权重计算:__sw_hweight 系列函数本代码片段提供了一组用于计算不同位宽整数(8、16、32、64位)汉明权重(Hamming Weight)的纯软件实现。汉明权重,又称“置位比特计数”(population count),指的是一个二进制数中 ‘1’ 的总个数。这些函数是内核中需要进行位操作统计时的基础工具,其实现采用了高效的、不依赖特定处理器指令的“分治”并行算法。 实现原理分析这些函数的核心是采用了一种经典的分治算法(Divide and Conquer),在对数时间内完成计算,远比逐位检查的方法高效。以 __sw_hweight32 为例,其算法步骤如下: 两比特分组求和:w -= (w >> 1) & 0x55555555; 0x55555555 的二进制表示为 01010101...。 (w >> 1) & 0x55555555 的作用是分离出...
fcntl
[toc] fs/fcntl.c 文件控制(File Control) 管理文件锁和文件描述符属性 历史与背景这项技术是为了解决什么特定问题而诞生的?fs/fcntl.c 实现的 fcntl() 系统调用是为了解决一个基本问题:在文件被打开之后,如何查询和修改其属性及状态。标准的 open(), read(), write(), close() 提供了对文件内容的基本I/O操作,但现实世界的应用程序需要更精细的控制能力,主要包括: 并发访问控制:当多个进程同时访问同一个文件时,如何防止数据损坏?这就需要一种机制来协调访问,即文件锁(File Locking)。 修改描述符行为:如何将一个阻塞的文件描述符(File Descriptor, FD)变为非阻塞的?如何防止一个打开的FD被子进程继承?这就需要对FD的属性进行管理。 复制文件描述符:如何创建一个新的FD,使其指向与现有FD相同的打开文件实例(struct file),例如用于重定向标准输入/输出。 fcntl() 被设计成一个多功能的“瑞士军刀”,通过一个单一的系统调用入口,提供了对上...
workingset
[toc] mm/workingset.c 工作集检测(Working Set Detection) 提升页面回收效率的热点内存识别机制历史与背景这项技术是为了解决什么特定问题而诞生的?mm/workingset.c 中的代码是为了解决传统页面回收算法(如vmscan.c中的两阶段LRU)的一个核心痛点:无法精确区分真正的“工作集”和短暂的、非核心的内存使用。 工作集(Working Set)指的是一个进程在当前阶段为了高效运行而需要频繁访问的内存页面集合。传统LRU算法通过active/inactive链表来近似这个集合,但存在以下问题: 抖动(Thrashing):当内存压力增大时,一个暂时不活动的进程(例如,用户切换到了另一个窗口),其工作集页面可能会被从active链表老化到inactive链表,并最终被回收。当用户切回该进程时,进程会遭遇大量的缺页中断(page faults),需要从磁盘或交换空间重新读取其工作集,导致系统响应缓慢,磁盘I/O飙升。workingset.c 的核心目标就是识别并保护这些被错误回收的工作集页面,从而抑...






