vmscan
[toc] mm/vmscan.c 页面回收(Page Reclaim) 内核内存管理的核心压力调节器历史与背景这项技术是为了解决什么特定问题而诞生的?mm/vmscan.c 中的代码是为了解决计算机科学中最基本的问题之一:物理内存是一种有限资源。当系统运行的应用程序和内核本身需要的内存总量超过了可用的物理RAM时,操作系统必须有一种机制来释放一些当前已分配但“不那么重要”的内存,以便为新的、更紧迫的内存请求腾出空间。 如果没有页面回收机制,系统在内存耗尽时唯一的选择就是拒绝新的内存分配请求,这将导致应用程序崩溃或系统完全停止响应。vmscan.c 实现的页面回收(Page Reclaim)算法,其核心目标是在内存压力(Memory Pressure)下,智能地选择并回收内存页面,从而保证系统的持续运行和响应能力。 它的发展经历了哪些重要的里程碑或版本迭代?Linux的页面回收算法经历了重大的演进,以适应不断变化的硬件和工作负载: 早期的LRU:最初的Linux内核使用了相当简单的“最近最少使用”(Least Recently Used, LRU)算法。 两阶...
utsname_sysctl
[TOC] kernel/utsname_sysctl.c UTS命名空间与Sysctl接口 管理和暴露系统标识信息历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了提供一个标准化的、可在运行时动态查询和修改系统核心标识信息的机制而诞生的。这些标识信息,统称为UTS(UNIX Time-sharing System)名称,包括: 主机名 (Hostname) 和 域名 (Domainname):在网络中唯一标识一台机器。 操作系统发布版本 (OS Release) 和 版本号 (Version):允许软件检查其运行的内核版本,以确定兼容性或是否存在特定功能/错误。 硬件架构 (Machine):指明系统运行的CPU架构(如 x86_64, aarch64)。 utsname_sysctl.c 的核心任务是: 提供访问接口:允许用户空间程序和管理员通过 uname(2) 系统调用和 /proc/sys/kernel/ 文件系统接口来读取这些信息。 提供配置能力:尤其是对于主机名和域名,系统必须提供一种在运行时进行修改的方法,而无需重启...
seccomp
[toc] kernel/seccomp.c 安全计算模式(Secure Computing Mode) 系统调用防火墙历史与背景这项技术是为了解决什么特定问题而诞生的?Seccomp(Secure Computing Mode)是为了解决一个核心的安全问题而诞生的:如何安全地运行不可信的代码。 在复杂的软件环境中,一个进程被赋予了访问数百个系统调用(syscall)的能力,这些系统调用是用户空间程序与内核交互的接口。 然而,大多数程序在其整个生命周期中只需要使用这些系统调用中的一小部分。 如果一个程序(例如,一个处理外部输入的Web浏览器渲染进程)被恶意代码攻陷,攻击者就可以利用那些该程序本不需要、但内核依然暴露给它的系统调用来进一步攻击和破坏整个系统。 Seccomp通过提供一种机制来限制一个进程可以调用的系统调用集合,从而减少内核的攻击面。 它的核心思想是实施“最小权限原则”:只授予程序执行其核心功能所必需的最小权限集合。 这样,即使程序被攻破,攻击者能造成的损害也因为其可用的系统调用极其有限而受到严格控制。 这对于构建应用程序沙箱(sandbox)至关重要...
Linux内核kallsyms符号压缩的完整构建流程
@[toc] Linux内核kallsyms符号压缩的完整构建流程 1. 引言Linux内核的kallsyms机制是其自省(Introspection)和调试能力的核心基石。它允许内核在运行时将内存地址解析为可读的符号名称,这对于错误追踪(Oops messages)、性能分析和内核调试至关重要。然而,在一个现代内核中,符号数量可达数十万之多,直接以字符串形式存储将消耗数兆字节的宝贵内存。 为了解决这一问题,内核构建系统采用了一套精巧的多趟链接(Multi-pass Linking)和符号压缩(Symbol Compression)流程。此流程由scripts/link-vmlinux.sh脚本调度,并使用一个专门的宿主工具scripts/kallsyms来执行核心的压缩算法。本文将完整地、分步骤地剖析这一流程,从构建脚本的宏观调度到压缩工具的微观算法实现。 2. 宏观调度:scripts/link-vmlinux.sh的多趟链接整个kallsyms数据的生成过程并非一次完成,而是通过一个迭代收敛的过程,以确保最终嵌入内核的符号地址是完全准确的。这个过程巧妙地解决了“测量行为...
link-vmlinux
[toc] scripts/Makefile.vmlinux输出文件 .tmp_vmlinux2.kallsyms.S .tmp_vmlinux2.kallsyms.o .tmp_vmlinux2.syms 123-rw-rw-r-- 1 embedsky embedsky 285K Oct 5 10:38 .tmp_vmlinux2.kallsyms.o-rw-rw-r-- 1 embedsky embedsky 2.9M Oct 5 10:38 .tmp_vmlinux2.kallsyms.S-rw-rw-r-- 1 embedsky embedsky 625K Oct 5 10:38 .tmp_vmlinux2.syms .tmp_vmlinux2.syms截取一点的内容如下所示 12345678910111213141516171819202122232400000000 A cpu_v7m_suspend_sizec0008000 T _textc0008000 T stextc0008028 t __vet_atagsc0008...
kallsyms
[TOC] linux-gnu/bits/getopt_ext.h getopt_long: GNU 命令行长选项解析接口本代码片段是一个 C 语言头文件(getopt_ext.h,通常被 getopt.h 包含),它定义了 GNU C 库中用于解析命令行参数的 getopt_long 函数及其核心数据结构 struct option。其主要功能是为命令行程序提供一个强大且灵活的机制,使其能够支持并解析长格式的选项(例如,--all-symbols),而不仅仅是传统的单字母短格式选项(如 -a)。 实现原理分析此机制的核心是通过一个描述符结构体数组,将命令行中的字符串与程序内部的变量和行为进行声明式映射。 选项描述符 (struct option): 这是整个机制的核心数据结构。开发者需要创建一个 struct option 类型的数组,数组中的每一个元素都完整地描述了一个长选项: const char *name: 定义了长选项的名称,即 -- 后面的字符串,例如 "all-symbols"。 int has_arg: 指定该选...
Linux内核kallsyms符号压缩与解压机制
@[toc] Linux内核kallsyms符号压缩与解压机制 1. 引言:为何需要kallsyms?在Linux内核的运行过程中,当发生错误(Oops)、进行性能剖析(Profiling)或使用调试器(Debugger)时,系统需要将内存中的函数地址转换为人类可读的符号名称。例如,将地址0xffffffff810a43c0转换为printk。这个地址到符号的映射表就是kallsyms(Kernel All Symbols)。 然而,内核包含数以万计的符号,如果将所有符号名称作为原始字符串直接存储在内核镜像中,会占用数兆字节的宝贵内存。为了解决这个问题,内核在编译时采用了一种高效的**“查表压缩”**方案,将符号名称字符串压缩成紧凑的字节序列。本文将深入剖析这一压缩数据的结构以及内核在运行时如何对其进行解压,还原出原始的符号名称。 123456789101112graph TD subgraph "内核编译时" A["所有符号名称"] --> B("scripts/kallsyms"); ...
commoncap
[TOC] include/linux/security.h12345678910111213141516/** * @brief security_capable - 检查凭证是否拥有特定能力(LSM钩子包装)。 * @param cred 待检查的进程凭证。 * @param ns 目标资源所属的用户命名空间。 * @param cap 要检查的能力编号。 * @param opts 附加选项。 * @return 0 表示拥有能力,-EPERM 表示没有。 */static inline int security_capable(const struct cred *cred, struct user_namespace *ns, int cap, unsigned int opts){ // 这是一个内联包装函数,直接调用底层的能力检查核心函数。 return cap_capable(cred, ns, cap, opts);} security/commoncap.c Linu...
kallsyms
[TOC] kernel/kallsyms.c 内核符号表(Kernel Symbols) 运行时内核符号解析 历史与背景这项技术是为了解决什么特定问题而诞生的?kallsyms(Kernel All Symbols)机制的诞生是为了解决在内核运行时动态解析符号地址的核心需求。一个符号(Symbol)是程序中的一个构建块,通常指代一个函数名或变量名。内核在运行时,更倾向于直接使用内存地址(如 0xffffffff81c33580)而不是符号名(如 schedule)。 然而,在很多场景下,将地址转换回人类可读的符号名是至关重要的: 内核调试与错误分析:当内核发生严重错误(Kernel Panic)或“oops”时,它会打印出当时的寄存器状态和函数调用栈(Call Trace)。 如果调用栈仅仅是一串十六进制地址,那么对于开发者来说几乎是无用的。kallsyms 机制使得内核能够在崩溃时,当场将这些地址解析成具体的函数名和偏移量,极大地简化了调试过程。 动态模块加载:内核模块(Loadable Kernel Modules, LKM)在加载时需要链接到内核主镜像中的...
clockevents
[TOC] kernel/time/clockevents.cclockevents_switch_state - 设置时钟事件设备的运行状态123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475static int __clockevents_switch_state(struct clock_event_device *dev, enum clock_event_state state){ if (dev->features & CLOCK_EVT_FEAT_DUMMY) return 0; /* Transition with new state-specific callbacks */ switch (state) { case CLOCK_EVT_STATE_DET...








