代码补丁
[TOC] static_call 和 jump_label 的区别及异同点static_call 和 jump_label 都是 Linux 内核中的优化机制,旨在提高性能,减少运行时的分支判断和间接调用开销。尽管它们的目标相似,但它们的实现方式和应用场景有所不同。 相同点 动态修改代码路径: 两者都支持在运行时动态修改代码路径,从而实现功能的启用或禁用。 通过修改指令(代码补丁),避免了传统的条件分支或间接调用的性能开销。 性能优化: 两者都旨在减少分支预测失败或间接调用的开销,适用于性能敏感的代码路径。 运行时灵活性: 两者都允许在运行时动态切换功能或行为,而无需重新编译或重启系统。 代码补丁机制: 两者都依赖于代码补丁(code patching)技术,通过修改内存中的指令来实现动态行为。 不同点 特性 static_call jump_label 主要用途 用于优化函数调用,将间接调用替换为直接调用。 用于动态启用或禁用代码块,优化条件分支判断。 优化的内容 函数调用路径(间接调用 → 直接调用)。 条件分支路径(条件判...
内核支持与数据
[toc] Makefile宏LINUX_ARM_ARCH12345678910111213141516//arch/arm/Makefile# Note that GCC does not numerically define an architecture version# macro, but instead defines a whole series of macros which makes# testing for a specific architecture or later rather impossible.cpp-$(CONFIG_CPU_32v7M) :=-D__LINUX_ARM_ARCH__=7cpp-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7cpp-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6# Only override the compiler option if ARMv6. The ARMv6K extensions are# always a...
内存管理与访问
[toc] include/linux/cache.h: 提供与CPU缓存行对齐相关的宏,如 ____cacheline_aligned__cacheline_aligned 缓存行对齐 这个修饰符确保变量在内存中对齐到缓存行的边界上。缓存行对齐可以减少缓存行冲突,提高缓存命中率,从而提高系统性能。在多处理器系统中,缓存行对齐尤为重要,因为多个处理器可能同时访问相同的内存区域。通过对齐,可以减少缓存一致性协议带来的开销。 在多处理器系统中,缓存行对齐可以减少缓存一致性协议带来的开销,主要原因如下: 缓存一致性协议:在多处理器系统中,每个处理器都有自己的缓存,用于存储频繁访问的数据。为了确保所有处理器看到的数据是一致的,系统使用缓存一致性协议(如MESI协议)。当一个处理器修改了某个缓存行中的数据,其他处理器必须更新或失效其缓存中的相应数据。这种一致性维护会带来额外的开销。 缓存行对齐的好处 减少伪共享:伪共享(False Sharing)是指多个处理器访问同一个缓存行中的不同数据项,导致频繁的缓存一致性操作。通过缓存行对齐,可以确保每个处理器访问的...
compiler
[toc] include/linux/build_bug.hstatic_assert 静态编译警告123456789101112131415161718/** * static_assert - 在构建时检查整数常量表达式 * * static_assert() 是 C11 _Static_assert的包装器,具有 * little 宏魔术使消息成为可选的(默认为 * 测试表达式的字符串化)。 * * 与 BUILD_BUG_ON() 相反,static_assert() 可以在 global * 范围,但要求表达式为整数常量 * 表达式(即,__builtin_constant_p() 是不够的 * true 表示 expr)。 * * 另请注意BUILD_BUG_ON,如果条件为 * true,而 static_assert() 如果表达式为 *假。 */#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)#define __static_ass...
底层CPU与体系结构宏
[toc] include/asm-generic/rwonce.h: 提供 READ_ONCE() 和 WRITE_ONCE() 宏,防止编译器优化,保证单次读写的原子性1234567/* * 阻止编译器合并或重新获取读取或写入。还禁止编译器对 READ_ONCE 和 WRITE_ONCE 的连续实例重新排序,但前提是编译器知道某些特定排序。使编译器了解 Sequences 的一种方法是将 READ_ONCE 或 WRITE_ONCE 的两次调用放在不同的 C 语句中。 * * 这两个宏也适用于聚合数据类型,如结构体或联合体。 * * 它们的两个主要用例是:(1) 调解进程级代码和 irq/NMI 处理程序之间的通信,所有处理程序都运行在同一个 CPU 上,以及 (2) 确保编译器不会折叠、纺锤或以其他方式破坏不需要排序或与提供所需排序的显式内存屏障或原子指令交互的访问。 */ compiletime_assert_rwonce_type __native_word 是一个宏,用于检查给定类型是否是本机字长(通常是 32 位或 64 位)。如果类型不...
通用工具与错误处理宏
[toc] include/linux/once_lite.h: (一次性调用) 提供确保某段代码在多核环境下只被精确执行一次的宏 每个宏仅在第一次使用时,执行函数功能.通过静态变量来实现一次性调用的功能 12345678910111213141516171819202122232425262728/* 调用一次函数。类似于 DO_ONCE(),但不通过jump label使用跳转标签修补。 */#define DO_ONCE_LITE(func, ...) \ DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__)//通过静态变量来实现一次性调用的功能#define __ONCE_LITE_IF(condition) \ ({ \ static bool __section(".data..once") __already_done; \ bool __ret_cond = !!(condition); \ bool __ret_once = fal...
通用数学与位操作宏
[toc] include/asm-generic/div64.h : 提供64位除法操作的通用实现# arch/arm/include/asm/div64.h1234567891011121314151617181920212223242526272829/* * __div64_32() 的语义是: * * uint32_t __div64_32(uint64_t *n, uint32_t base) * { * uint32_t remainder = *n % base; * *n = *n / base; * return remainder; * } * * 换句话说,一个 64 位的被除数和一个 32 位的除数产生 64 位的结果和 32 位的余数。 为了以最佳方式实现这一点,我们覆盖了 lib/div64.c 中的通用版本,以使用完全非标准参数和结果调用约定的 __do_div64 程序集实现(当心)。 */static inline uint32_t __div64_32...
boot
[TOC] arch/arm/boot: Linux 32位ARM架构的启动基石arch/arm/boot 目录是 Linux 内核源码中专门为 32 位 ARM 架构(AArch32)设计的启动代码所在地。它的核心使命是充当引导加载程序(Bootloader,如 U-Boot)与体系结构无关的通用内核代码之间的桥梁。这个目录下的代码负责处理内核启动最初始、最底层的阶段,为 C 语言环境的建立和主内核的执行做好万全准备。 一、 核心职责arch/arm/boot 目录下的代码和构建脚本共同完成了以下几项至关重要的任务: 生成可启动的内核镜像: 该目录下的 Makefile 是构建过程的核心,它负责将编译好的内核 vmlinux(一个 ELF 格式的文件)进行处理,最终生成 Bootloader 可以直接加载和执行的镜像格式,最常见的有 zImage 和 uImage。 内核解压缩: 为了减小存储体积和加快加载速度,内核镜像通常是经过压缩的。arch/arm/boot 包含了一个微型的、自解压的前端程序(Decompressor)。当 Bootloader...
debug
[TOC] arch/arm/include/debug/stm32.Saddruart 添加debug串口地址1234.macro addruart, rp, rv, tmp ldr \rp, =CONFIG_DEBUG_UART_PHYS @ physical base ldr \rv, =CONFIG_DEBUG_UART_VIRT @ virt base.endm CONFIG_DEBUG_UART_PHYS 和 CONFIG_DEBUG_UART_VIRT1234567891011121314151617//arch/arm/Kconfig.debugconfig DEBUG_UART_VIRT default DEBUG_UART_PHYS if !MMUconfig DEBUG_UART_PHYS default 0x40011000 if STM32F4_DEBUG_UART || STM32F7_DEBUG_UART || \ STM32H7_DEBUG_UARTconfig STM32H7_DEBUG_UART b...
assembly
[TOC] THUMB2指令集THUMB2 指令集深度解析:从入门到精通THUMB2 指令集是在嵌入式系统领域广受欢迎的 ARM 架构的一项关键技术。它巧妙地结合了 16 位指令的紧凑代码密度和 32 位指令的强大性能,为资源受限的设备提供了高效的解决方案。本文将从历史背景、核心原理、应用场景、入门实践、安全考量、生态系统、性能监控和未来趋势等多个维度,为您全面解析 THUMB2 指令集。 一、 历史与背景为了解决什么特定问题而诞生? THUMB2 技术的诞生主要是为了解决早期 ARM 架构在嵌入式应用中的一个核心矛盾:性能与代码密度之间的权衡。 ARM 指令集:提供强大的 32 位指令,性能出色,但指令均为 32 位定长,导致代码体积较大,对于内存(尤其是昂贵的片上闪存和 RAM)有限的嵌入式系统而言,成本较高。 Thumb 指令集(第一代):作为对策,ARM 推出了 16 位的 Thumb 指令集,它是 ARM 指令集的一个子集。 这显著减小了代码体积(约 30%-40%),降低了功耗和内存需求。 然而,Thumb 指令集功能有限,性能相比 32 位 ARM 指令集有所下降...








