zlib
[TOC] lib/zlib_inflate/inflate.c & lib/zlib_deflate/deflate.c DEFLATE压缩与解压缩历史与背景这项技术是为了解决什么特定问题而诞生的?内核中集成的 zlib 库是为了提供一个通用、可靠且经过充分验证的数据压缩和解压缩方案。数据压缩的根本目标是通过算法减少数据占用的存储空间或网络传输带宽。在内核这个层面,引入 zlib 主要解决了以下具体问题: 节省存储空间:对于存储受限的系统(尤其是早期的嵌入式设备),需要通过压缩文件系统来存储更多的内容。 加快启动速度:Linux内核镜像本身可以被压缩。在启动时,一个小型解压程序(stub)会先解压内核镜像到内存中再执行。虽然解压需要CPU时间,但从慢速存储设备(如早期的磁盘、Flash)读取一个较小的压缩文件所需的时间,远少于读取一个大的未压缩文件的时间,因此总体上加快了启动速度。 提高网络效率:在一些网络协议(如PPP)中,对传输的数据进行压缩可以显著减少网络带宽的占用。 内存优化-:通过在内存中创建压缩的块设备(RAM...
regmap
[TOC] regmapRegmap 简介Regmap 是 Linux 内核中的一个子系统,用于抽象和管理设备寄存器的访问。它为驱动程序提供了统一的接口,支持多种总线(如 I2C、SPI、MMIO 等)上的寄存器操作,同时提供了缓存、锁机制和调试功能。Regmap 的设计目标是简化驱动开发,减少重复代码,并提高寄存器访问的效率和安全性。 工作原理1. 核心概念 寄存器映射 (Register Map):Regmap 将设备的寄存器抽象为一个统一的映射,屏蔽了底层总线的差异。 寄存器缓存:Regmap 提供了可选的寄存器缓存机制,用于减少总线访问次数,提高性能。 寄存器访问控制:通过配置文件(struct regmap_config),可以定义哪些寄存器是可读、可写或易失的。 总线适配器:Regmap 支持多种总线(如 I2C、SPI、MMIO 等),通过总线适配器实现具体的读写操作。 2. 数据结构 struct regmap:表示寄存器映射的核心数据结构,包含寄存器的地址、值、缓存等信息。 struct regmap_config:配置寄存器映射的结构体,用于定义...
search
[TOC] include/linux/bsearch.h 二分查找bsearch12345678910111213141516171819202122232425262728293031323334353637383940414243/* * bsearch - 对元素数组进行二进制搜索 * @key:指向正在搜索的项目的指针 * @base:指向要搜索的第一个元素的指针 * @num:元件数量 * @size:每个元素的大小 * @cmp:指向比较功能的指针 * * 此函数对给定数组进行二进制搜索。 数组的内容应该已经在提供的比较函数下按升序排序。 * * 请注意,键不必与数组中的元素具有相同的类型,e.g. key可以是字符串,比较函数可以将字符串与结构体的 name 字段进行比较。 但是,如果数组中的键和元素属于同一类型,则可以对 sort() 和 bsearch() 使用相同的比较函数。 */void *bsearch(const void *key, const void *base, size_t num, size_t size, cmp_fu...
sort
[TOC] lib/sort.c 通用的排序库(Generic Sorting Library) 为内核提供标准的、高效的排序功能历史与背景这项技术是为了解决什么特定问题而诞生的?lib/sort.c 是为了解决一个在大型软件项目中普遍存在的问题——代码重复——而诞生的。在内核的各个子系统和驱动程序中,经常需要对一组数据进行排序。例如,根据优先级对任务进行排序、根据内存地址对设备资源进行排序等。 在lib/sort.c这个通用库出现之前,各个子系统可能会: 实现自己的、简陋的排序算法(如冒泡排序、插入排序)。 从其他地方复制粘贴一个更高效的排序算法(如快速排序)的实现。 这两种做法都导致了严重的问题:代码库中充满了功能相同但实现各异的排序代码,这不仅增加了内核的体积,也使得bug修复和性能优化变得极其困难。lib/sort.c的诞生,就是为了提供一个单一的、经过充分测试的、高性能的、通用的排序实现,供整个内核使用,从而消除代码重复,并保证排序操作的质量和效率。 它的发展经历了哪些重要的里程碑或版本迭代?lib/sort.c的核心是提供一个与标准C库qsort()函数...
bounds
[TOC] kernel/bounds.c 内核边界定义(Kernel Bounds Definition) 为汇编代码提供C语言的宏常量历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术以及其背后独特的构建过程,是为了解决一个根本性的、存在于所有操作系统内核开发中的问题:如何在底层汇编代码(Assembly Code)中,安全、准确地访问C语言定义的内核数据结构(structs)的成员偏移量和大小。 汇编代码的局限性:汇编语言是一种低级语言,它没有struct或#define的概念。汇编代码需要知道一个结构体中某个成员的确切字节偏移量才能访问它。例如,为了访问task_struct结构中的state字段,汇编代码需要知道state字段距离task_struct结构体起始地址有多少个字节。 C语言编译器的不确定性:这些偏移量并不是固定的。它们会因为以下原因而改变: 架构差异:同一个结构体在32位和64位系统上的布局可能完全不同。 配置选项:不同的内核配置选项(Kconfig)可能会启用或禁用某些结构体成员,导致其后所有成员的偏移量发生变化。 编译器行为:...
async
[toc] kernel/async.c 内核异步函数调用(Asynchronous Function Calls) 一个简单的“发后即忘”式内核执行框架历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术以及其实现的异步函数调用(async)框架,是为了解决内核中一个特定的并发需求:以最简单的方式,将一个函数的执行推迟到一个独立的上下文中,而调用者无需等待其完成。 优化启动时间:这是async框架诞生的最主要驱动力。在内核启动过程中,有大量的初始化调用(initcalls)。如果严格按照顺序依次执行,会非常耗时。async框架允许内核将那些没有严格依赖关系的、耗时的初始化函数“并行化”,将它们提交到后台异步执行,而主启动流程可以继续进行。这显著缩短了系统的总启动时间。 降低关键路径延迟:在某些性能敏感的代码路径中(例如一个设备驱动的.probe函数),可能会有一些耗时但非必需的初始化步骤。通过async,可以将这些步骤“发后即忘”(fire-and-forget)地交由后台处理,使得关键路径函数可以更快地返回,提高系统响应速度。 提供比工作队列更简单的接...
completion
[toc] kernel/sched/completion.c 内核同步原语(Kernel Synchronization Primitive) 简洁的任务完成信号量历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术以及它所实现的“完成量”(Completion),是为了提供一个高度简化的、专门用于解决“一个执行单元等待另一个执行单元完成某项工作”这一特定同步场景的内核原语。 简化样板代码:在completion出现之前,要实现这种“等待-通 知”的模式,开发者必须手动组合更底层的原语。这通常意味着: 1. 定义一个`wait_queue_head_t`(等待队列头)。 2. 定义一个`bool`或`int`类型的标志位来表示任务是否完成。 3. 等待者需要在一个循环中调用`wait_event_interruptible()`,这个宏会自动处理将任务加入等待队列、睡眠、被唤醒后检查标志位、处理伪唤醒等一系列复杂操作。 4. 完成者需要设置标志位,然后调用`wake_up()`来唤醒等待者。 ...
cpu
[toc] include/linux/cpumask.hcpumask_check 验证当前cpu数量是否超过了配置的最大cpu数量,并返回cpu1234567891011121314151617// 验证当前cpu数量是否超过了配置的最大cpu数量static __always_inline void cpu_max_bits_warn(unsigned int cpu, unsigned int bits){#ifdef CONFIG_DEBUG_PER_CPU_MAPS WARN_ON_ONCE(cpu >= bits);#endif /* CONFIG_DEBUG_PER_CPU_MAPS */}/* verify cpu argument to cpumask_* operators *///验证当前cpu数量是否超过了配置的最大cpu数量static __always_inline unsigned int cpumask_check(unsigned int cpu){ //small_cpuma...
exit
[TOC] kernel/exit.c 进程终结与资源回收(Process Termination and Resource Reclamation)历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/exit.c 内的代码是为了解决操作系统中最基本和最核心的问题之一:如何安全、彻底地终结一个正在运行的进程,并确保其占用的所有系统资源都被完全回收。 一个进程在运行时会占用各种系统资源,包括: 内存:进程地址空间(代码、数据、堆、栈)、页表。 文件描述符:打开的文件、套接字、管道等。 CPU时间:进程作为被调度的实体。 内核数据结构:如 task_struct、信号处理器、定时器等。 子进程关系:作为其他进程的父进程。 如果没有一个健壮、集中的退出机制,当进程结束时: 资源泄漏:内存、文件句柄等资源将无法被释放,随着时间推移会耗尽系统资源,导致系统崩溃。 产生僵尸进程:父进程需要一种机制来获知其子进程的退出状态。如果子进程直接消失,父进程将无法进行后续处理。 孤儿进程问题:如果一个父进程先于其子进程退出,这些子进程将成为“孤儿”,必须有一个机制来“...
cred
[TOC] kernel/cred.c 凭证管理(Credential Management) 内核中任务身份与权限的核心历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术以及其核心数据结构struct cred,是为了解决在现代多用户、多进程操作系统中一个根本性的安全问题:如何安全、高效、无竞争地管理和访问一个任务(进程或线程)的身份和权限集合。 集中化身份信息:一个任务的“身份”是复杂的,它包含了用户ID(UID)、组ID(GID)、补充组列表、安全标签(如SELinux上下文)、权能(Capabilities)等一系列信息。在struct cred出现之前,这些信息分散地存储在task_struct(进程描述符)中。 解决竞态条件与锁争用:直接修改task_struct中的权限字段是一个巨大的安全隐患。例如,如果一个线程正在修改自己的UID,而另一个线程同时在检查这个UID以决定是否允许某个操作,就会产生严重的竞态条件。为了保护这些字段,task_struct需要一个锁,但这在高并发系统(如大型Web服务器)中会成为严重的性能瓶颈,因为权限检查是内...








