init
[TOC] init/init_task.c 内核线程的一个核心特征是:它们没有自己独立的用户地址空间。它们只在内核空间运行,而内核地址空间是所有进程共享的。因此,内核线程不需要一个属于自己的内存描述符 struct mm_struct,所以它们的 task->mm 指针通常是 NULL init_task 就是大名鼎鼎的 PID 0 进程,也常被称为 swapper 进程。从它的标志位 .flags = PF_KTHREAD 可以看出,它是一个内核线程。 init_task 的调度策略(policy)是 SCHED_NORMAL,这意味着它是一个普通的分时调度任务,而不是实时任务。但是初始化阶段调用了init_idle(),使得它的sched_class 是 SCHED_IDLE,这样它就可以作为 CPU 的空闲任务运行。但是fork出来的其他进程继承的还是 SCHED_NORMAL 策略。 进程的“始祖”:init_task 是系统中所有进程的祖先。在系统启动后,它会创建第一个内核线程 kernel_init(它最终会成为 PID 1 的...
bio
[toc] include/linux/bio.hBIO 迭代器与数据段访问接口 (bio_iter, bio_advance_iter)核心功能该代码片段定义了一系列宏和static inline函数,它们共同构成了一个用于遍历和操作 struct bio(块 I/O 请求的基本单元)中数据段(bio_vec)的API。其核心功能是为块设备驱动提供一个标准、高效且安全的接口,用于: 访问当前数据段: 获取当前 I/O 进度(由 bio->bi_iter 迭代器所指向位置)的物理页、页内偏移和数据长度。 迭代遍历: 提供遍历 bio 中所有数据段的机制。 更新进度: 在驱动处理完一部分数据后,精确地更新 bio 的 bi_iter 迭代器,使其指向下一个待处理的数据位置。 状态查询: 提供辅助函数来查询 bio 的状态,例如数据方向(读/写)、是否包含有效数据等。 实现原理分析 迭代器设计模式: 这套 API 的核心设计思想是迭代器模式。struct bio 内部包含一个 struct bvec_iter bi_i...
blk-ioc
[toc] block/blk-ioc.c I/O上下文管理(I/O Context Management) 进程I/O优先级的关联与继承历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了解决在多任务操作系统中,如何区分和管理不同进程发起的I/O请求的重要性,从而实现更智能、更公平的I/O调度。 在blk-ioc.c(I/O Context)所代表的机制出现之前,内核的I/O调度器(I/O Scheduler)对所有进程发起的I/O请求几乎一视同仁。这会导致严重的问题: 优先级反转:一个高优先级的CPU密集型任务(如交互式桌面应用)可能会因为一个低优先级的后台I/O密集型任务(如文件索引、备份)而变得卡顿。后台任务产生的大量磁盘I/O请求会填满I/O队列,使得前台应用的关键数据读写请求需要等待很长时间。 资源争用不公:多个进程同时进行磁盘读写时,无法区分哪些进程的I/O应该被优先满足。例如,一个正在播放视频的媒体播放器和...
block
[toc] Linux 源码中的 block 目录:块设备 I/O 的核心中枢block 目录是 Linux 内核 I/O 栈的心脏。它负责管理所有块设备(如硬盘驱动器 HDD、固态硬盘 SSD、U 盘等)的数据交换。这一层的主要目标是提供一个通用的、高效的框架,将上层文件系统和应用程序的 I/O 请求,转化为底层具体硬件驱动程序可以执行的操作。 一、 历史与背景这项技术是为了解决什么特定问题而诞生的? block 层的诞生是为了解决两个核心问题: 抽象与解耦:如果没有一个通用的块设备层,每个文件系统(如 ext4, XFS)都需要自己编写直接与各种硬盘驱动(SATA, SCSI, NVMe)对话的代码。这会导致代码冗余、开发复杂且难以维护。block 层提供了一个标准的接口,使得文件系统无需关心底层硬件的具体细节,反之亦然。 性能优化:对存储设备的随机访问通常效率很低,尤其是在机械硬盘上,会导致磁头频繁寻道,浪费大量时间。block 层通过引入 I/O 调度器 (I/O Scheduler),可以对传入的 I/...
blk-mq
[toc] block/blk-mq.c 多队列块层核心(Multi-Queue Block Layer Core) 现代存储I/O性能的基石历史与背景这项技术是为了解决什么特定问题而诞生的?blk-mq(Block Multi-Queue)框架的诞生是为了从根本上重构Linux的块设备层,以适应现代存储硬件的飞速发展,特别是高速闪存设备(SSD、NVMe)的出现。 传统的Linux块层(single-queue block layer)是为机械硬盘(HDD)设计的,其核心是一个per-device的单一请求队列。这种设计在HDD时代是合理的,因为磁盘的机械寻道时间是主要瓶颈。然而,随着能够处理数十万甚至数百万IOPS(每秒I/O操作数)的闪存设备的普及,这个单一队列的设计成为了新的、严重的性能瓶颈: 锁争用:在多核CPU系统上,所有核心提交I/O时都必须争抢保护这个单一队列的全局锁。这种锁争用导致CPU无法有效扩展,即使硬件有能力处理更多请求,软件层面也无法将请求高效地提交给硬件。 缓存行弹跳:对单一队列的频繁访问导致其数据所在的...
genhd
[toc] block/genhd.c 通用硬盘驱动(Generic Hard Disk Driver) 内核中块设备的表示与管理历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了在Linux内核中创建一个统一的、抽象的块设备表示,以解决如何管理和表示各种各样的块存储设备(如硬盘、软盘、U盘、RAID卷等)的问题。 在genhd.c(Generic Hard Disk)所代表的框架出现之前,内核中对不同类型块设备的管理是零散和不一致的。genhd.c的诞生旨在解决以下核心问题: 设备抽象:需要一个通用的数据结构来描述一个块设备,无论它是物理硬盘、一个硬盘上的分区,还是一个由多个磁盘组成的逻辑卷。这个结构就是struct gendisk。 分区管理:一个物理磁盘通常被划分为多个分区。内核需要一个标准的机制来发现、解析和表示这些分区,并将每个分区也作为一个独立的块设备呈现给上层。genhd.c负责扫描分区表并为每个分区创建设备节点。 设备注册与命名:需要一个统一的机制来向内核注册新的块设备,并为其分配一个唯一的设备号(major/minor ...
anon_inodes
[toc] ![]](https://i-blog.csdnimg.cn/direct/c915e9f9c7304594b143431d7f9abba9.png) fs/anon_inodes.c 匿名inode文件系统(Anonymous Inode Filesystem) 提供内核事件驱动的文件描述符历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了给那些纯粹基于内核内部事件、而没有实体文件系统后端的对象提供一个标准的文件描述符(File Descriptor)接口而诞生的。 在Linux“一切皆文件”的设计哲学下,将各种资源抽象为文件描述符,可以使用read(), write(), poll(), epoll()等一套统一的I/O接口来进行操作。 在anon_inodes出现之前,如果内核想提供一个事件通知机制(例如inotify),它可能需要实现一个迷你的、私有的伪文件系统,只为了创建一个inode和一个file对象返回给用户空间。 这导致了代码的重复和资源的浪费。 anon_inodes.c解决的核心问题是:如何以一种轻量级、标准化...
binfmt_script
[TOC] include/uapi/linux/elf.hElf32_Ehdr (内核中通常用 struct elfhdr): ELF文件头结构体这个结构体是ELF文件格式的“封面”和“目录”,它必须位于任何一个ELF文件的最开头。加载器(如内核)通过读取并解析这个结构体,来了解如何处理文件的其余部分。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687/* * 这是32位ELF文件头的标准定义. * 内核代码中通常会用 Elf32_Addr, Elf32_Half 等类型来保证在不同架构下的大小是固定的. */typedef struct elf32_hdr { /* * e_ident: 一个16字节的数组, 用于识别文件. 它包含了多个子字段....
buffer
[TOC] fs/buffer.c 缓冲区管理(Buffer Management) 块设备I/O的核心缓冲层历史与背景这项技术是为了解决什么特定问题而诞生的?fs/buffer.c 及其实现的**缓冲区缓存(Buffer Cache)**是Linux/Unix系统中最古老、最核心的性能优化机制之一。它最初是为了解决一个根本性的问题:物理磁盘I/O操作极其缓慢。 性能瓶颈:相比于CPU和内存的速度,机械硬盘的读写速度要慢上几个数量级。如果每次读写请求都直接访问磁盘,系统性能将严重受限。 提供抽象:内核需要一种方法来为文件系统提供一个统一的、基于块(Block)的设备视图,隐藏底层硬件的复杂性。 缓冲区缓存通过在物理内存(RAM)中缓存磁盘块的内容来解决这个问题。当内核需要读取一个磁盘块时,它首先检查该块是否已经在缓存中。如果在,就直接从内存中读取,避免了昂贵的物理I/O。同样,写操作可以先写入缓存(标记为“脏”),然后由内核在稍后的“最佳”时机批量写回磁盘。 它的发展经历了哪些重要的里程碑或版本迭代?缓冲区缓存的发展史是...
dcache
[TOC] fs/dcache.c 目录项缓存(Directory Entry Cache) VFS路径查找加速器历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术以及它所实现的目录项缓存(dcache),是为了解决Linux虚拟文件系统(VFS)中最核心的性能瓶颈之一:路径名到inode的解析过程。 消除磁盘I/O:在一个典型的文件系统中,解析一个路径如/home/user/file.txt需要一系列的磁盘读取操作。首先读取根目录/的内容找到home,然后读取home目录的内容找到user,以此类推,直到最后找到file.txt。每一次目录读取都是一次缓慢的磁盘I/O。如果每次open()或stat()系统调用都执行这个过程,系统性能将无法接受。 提供快速路径查找:dcache在内存中缓存了目录项(dentry)的树状结构,它直接映射了文件系统的目录层次。当内核需要解析一个路径时,它首先在dcache中查找。如果路径的所有组件都在缓存中,整个解析过程就可以在内存中以极高的速度完成,完全无需访问磁盘。 缓存负面结果(Negative ...









