【免费下载链接】linux-insides-zhLinux 内核揭秘项目地址https://gitcode.com/hust-open-atom-club/linux-insides-zh点击查看免费下载Linux 内核的定时器与时间管理子系统是驱动 TCP 超时、任务调度、异步函数触发、下一事件中断调度等核心功能的基石。本文以 Timers 章节为主线从内核启动路径中时间管理相关函数的调用顺序出发系统讲解jiffies、clocksource、tick broadcast、dyntick、动态定时器、clockevents以及 x86_64 时钟源和时钟系统调用的实现原理帮助你建立从硬件计数器到用户态时间的完整知识链路。章节导读Timers/README 覆盖的七大主题本章节由 7 篇连载文章组成每篇对应内核时间管理的一个核心抽象简介——从setup_arch起步介绍jiffies与clocksource两个基础概念及其初始化时钟源框架简介——深入clocksource框架的注册、选择与 sysfs 接口tick broadcast 框架与 dyntick——讲解处理器进入深度睡眠后由谁唤醒、以及无 tickNO_HZ模式定时器介绍——动态定时器软件定时器的数据结构与运行机制Clockevents 框架简介——与 clocksource 互为概念反转的时钟事件设备管理框架x86 相关的时钟源——逐一分析 HPET、ACPI PM、TSC 三个 x86_64 时钟源时钟相关的系统调用——从用户态gettimeofday、clock_gettime、nanosleep一路追踪到内核实现。阅读本文后你将能够理解jiffies与HZ的关系并熟练使用超时表达式看懂dmesg中时钟源注册与切换日志掌握通过 sysfs 查看/切换时钟源的方法理解动态定时器与 clockevents 框架的 API 用法最终具备独立阅读kernel/time/与arch/x86/kernel/下时间管理代码的能力。jiffies 与 clocksource时间管理的两个起点内核启动路径中的时间管理函数内核解压完成后架构无关代码从 init/main.c 附近的start_kernel开始执行。在setup_arch函数中可以看到第一个与时间管理相关的调用x86_init.timers.wallclock_init();x86_init结构体struct x86_init_ops为不同平台如 Intel MID、Intel CE4100保存了一组默认 setup 函数指针其中timers字段类型为x86_init_timers包含四个函数指针setup_percpu_clockev——为 boot CPU 建立 per-CPU 时钟事件设备tsc_pre_init——TSC 初始化之前调用的平台函数timer_init——初始化平台定时器wallclock_init——初始化墙钟wallclock设备。标准 PC 硬件上wallclock_init指向空操作函数x86_init_noop仅 Intel MID 平台会将其替换为intel_mid_rtc_init该函数解析 Simple Firmware Interface 的 M-RTC 表并设置x86_platform.get_wallclock/set_wallclock。紧接着setup_arch中还有第二个关键调用register_refined_jiffies(CLOCK_TICK_RATE);jiffies系统启动以来的 tick 计数jiffies是 Linux 内核中的全局变量保存系统启动以来发生的时钟中断tick次数初始化时置零每次定时器中断递增。内核同时定义了两个相关变量extern unsigned long volatile __jiffy_data jiffies; extern u64 jiffies_64;实际生效的变量取决于处理器类型x86_64 使用u64x86_32 使用unsigned long即jiffies_64的低 32 位这一映射由链接脚本 arch/x86/kernel/vmlinux.lds.S 完成。jiffies的读出必须通过read_seqbegin/read_seqretry保护的 seqlock 机制见kernel/time/jiffies.c中get_jiffies_64的实现原因是有一些机器无法原子地读取完整的 64 位值。clocksource硬件计数器的抽象层不同硬件提供的时钟源能力差异巨大x86 片上的 TSC 频率可等于处理器频率HPET 是至少 10 MHz 的 64 位计数器。为统一管理这些硬件内核引入clocksource概念——硬件抽象的自由运行计数器为内核提供时间值。以 jiffies 为例其 clocksource 定义为static struct clocksource clocksource_jiffies { .name jiffies, .rating 1, .read jiffies_read, .mask 0xffffffff, .mult NSEC_PER_JIFFY JIFFIES_SHIFT, .shift JIFFIES_SHIFT, .max_cycles 10, };关键字段说明rating时钟源管理代码据此选择最佳时钟源取值范围与含义如下1-99——仅用于启动和测试100-199——可用于实际使用但不理想200-299——正确可用的时钟源如 HPET 为 250、acpi_pm 为 200300-399——相当快且准确的时钟源如 TSC 为 300400-499——理想时钟源可用时必选。mask非 64 位计数器的减法无需特殊溢出逻辑。jiffies 的 mask 是 32 位0xffffffff意味着约 42 秒后回绕到零。mult / shift将计数器原始值转换为纳秒转换公式为((u64) cycles * mult) shift。jiffies 的mult NSEC_PER_JIFFY JIFFIES_SHIFT其中NSEC_PER_JIFFY (NSEC_PER_SEC HZ/2) / HZJIFFIES_SHIFT依 HZ 取值HZ 34时为 6HZ 67时为 7否则为 8。max_cycles可安全相乘而不溢出溢出可能的最大周期值。HZ代表系统定时器频率由CONFIG_HZ配置项决定。在 x86 上定义为#define HZ CONFIG_HZ可选值见内核配置菜单x86 默认CONFIG_HZ_1000y对应HZ1000此时定时器中断每秒发生 1000 次若选择 250 HZ则每 4ms 一次中断。register_refined_jiffies 的注册流程register_refined_jiffies(CLOCK_TICK_RATE)的核心目标是注册refined_jiffies时钟源。它与标准clocksource_jiffies的区别在于标准 jiffies 的分辨率受限于定时器中断频率HZ精度可能不足refined_jiffies则以CLOCK_TICK_RATE为基准获得更高精度。其中CLOCK_TICK_RATE展开为PIT_TICK_RATE即 Intel 8253 可编程间隔定时器的频率1193182 Hz。实现要点kernel/time/jiffies.crefined_jiffies clocksource_jiffies; refined_jiffies.name refined-jiffies; refined_jiffies.rating; /* 由 1 提升到 2成为时钟源管理代码的最佳候选 */随后计算每个 tick 的周期数、通过移位获得额外精度最终调用__clocksource_register(refined_jiffies)完成注册。使用 jiffies 的实战表达式jiffies / HZ可得到系统运行秒数uptime。内核中大量使用jiffies n*HZ设定未来超时点/* 从现在起 30 秒 */ jiffies 30*HZ /* 从现在起 2 分钟 */ jiffies 120*HZ /* 从现在起 1 毫秒 */ jiffies HZ / 1000配合time_before/time_after_eq等宏即可实现超时轮询例如arch/x86/kernel/smpboot.c的do_boot_cpu中等待应用处理器 10 秒响应或sound/isa/sscape.c中obp_startup_ack等待声卡启动确认。这是内核中最常见的超时编程模式。clocksource 框架深入注册、选择与 sysfsclocksource 结构全字段解析clocksource结构定义于include/linux/clocksource.h除前面见过的字段外还包括read——返回计数器周期值cycle_t即u64的函数指针max_idle_ns——允许的最大空闲时间纳秒服务于启用CONFIG_NO_HZ的内核动态 tick 允许内核休眠超过单个 tick 甚至无限长该字段即休眠上限maxadj——mult的最大调整值用于校正((u64) cycles * mult) shift的舍入误差并防止调整后mult溢出enable/disable/suspend/resume——启用、禁用、挂起、恢复回调owner——所属内核模块的引用。受配置选项影响的字段还有两类CONFIG_ARCH_CLOCKSOURCE_DATAx86/IA64 专属的arch_clocksource_data其中vclock_mode标识 vDSO 时钟模式VCLOCK_NONE0、VCLOCK_TSC1、VCLOCK_HPET2、VCLOCK_PVCLOCK3CONFIG_CLOCKSOURCE_WATCHDOGwd_list、cs_last、wd_last三个看门狗相关字段仅 x86 架构启用该选项——因为 TSC 需要对照其他时钟源验证。注册新时钟源的 API 与调用链注册 API 共有三个等价入口static inline int __clocksource_register(struct clocksource *cs) { return __clocksource_register_scale(cs, 1, 0); } static inline int clocksource_register_hz(struct clocksource *cs, u32 hz) { return __clocksource_register_scale(cs, 1, hz); } static inline int clocksource_register_khz(struct clocksource *cs, u32 khz) { return __clocksource_register_scale(cs, 1000, khz); }三者最终都调用kernel/time/clocksource.c中的__clocksource_register_scale(cs, scale, freq)。该函数先调用__clocksource_update_freq_scale计算mult/shift若频率非零再在clocksource_mutex保护下依次执行clocksource_enqueue(cs); /* 按 rating 排序插入 clocksource_list */ clocksource_enqueue_watchdog(cs); /* 按标志插入看门狗链表 */ clocksource_select(); /* 选择最佳时钟源 */clocksource_enqueue遍历已注册列表按rating降序找到插入点clocksource_select内部为__clocksource_select(false)从链表头取出 rating 最高的时钟源并切换if (curr_clocksource ! best !timekeeping_notify(best)) { pr_info(Switched to clocksource %s\n, best-name); curr_clocksource best; }dmesg中可以观察到上述过程的完整轨迹$ dmesg | grep clocksource: [ 0.000000] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1910969940391419 ns [ 0.000000] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 133484882848 ns [ 0.094084] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns [ 0.205302] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns [ 1.452979] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x7350b459580, max_idle_ns: 881591204237 nssysfs 接口查看与切换时钟源init_clocksource_sysfs通过device_initcall注册clocksource子系统创建/sys/devices/system/clocksource/目录及三个属性文件current_clocksource、unbind_clocksource、available_clocksource。实战用法$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm $ cat /sys/devices/system/clocksource/clocksource0/current_clocksource tsc注意jiffies与refined_jiffies不会出现在可用列表中——该文件只映射带CLOCK_SOURCE_VALID_FOR_HRES标志的高分辨率时钟源。tick broadcast 框架与 dyntick让空闲处理器睡得更深tick_init 与 idle 进程start_kernel中setup_arch之后第一个时间管理相关调用是tick_init()kernel/time/tick-common.cvoid __init tick_init(void) { tick_broadcast_init(); tick_nohz_init(); }tick_broadcast_init初始化 tick broadcast 框架tick_nohz_init初始化无 ticktickless模式数据结构。背景问题在于当处理器运行cpu_idle_loop空闲循环时系统定时器中断对功耗管理几乎无意义——空闲处理器没必要被周期性中断打扰。两种省电模式Linux 内核提供两种省略调度时钟中断的方式CONFIG_NO_HZ_IDLEdyntick-idle 模式空闲处理器不再接收周期性定时器中断改为按需中断。进入空闲时调用tick_nohz_idle_enter退出时调用tick_nohz_idle_exit均在kernel/time/tick-sched.cCONFIG_NO_HZ_FULLfull dynticks空闲处理器以及只有一个可运行任务的忙碌处理器都省略调度时钟中断大幅减少定时器中断次数。tick broadcast谁唤醒沉睡的处理器当处理器进入深度睡眠cpuidle 框架的 C-states时其本地定时器可能停止工作此时需要一个不受 C-states 影响的定时器负责唤醒。tick broadcast 框架正是为此而生。tick_broadcast_init通过zalloc_cpumask_var分配多个 cpumasktick_broadcast_mask——处于睡眠模式的处理器位图tick_broadcast_on——处于周期性广播状态的处理器位图tmpmask——临时位图tick_broadcast_oneshot_mask/tick_broadcast_pending_mask/tick_broadcast_force_mask——仅在CONFIG_TICK_ONESHOT下分配对应 oneshot 模式下的通知、挂起与强制广播。时钟事件设备可处于两种模式CLOCK_EVT_FEAT_PERIODIC周期性事件与CLOCK_EVT_FEAT_ONESHOT一次性事件。新时钟事件设备注册时tick_check_new_device会调用tick_install_broadcast_device判断其能否充当广播设备先通过tick_check_broadcast_device检查features与rating再用clockevents_exchange_device替换旧设备最后在tick_broadcast_mask非空时以tick_broadcast_start_periodic启动周期模式。中断到来时HPET 的hpet_interrupt_handler调用hevt-event_handler(hevt)最终经tick_do_broadcast发送 IPI 唤醒目标处理器集合。NO_HZ 数据结构的初始化tick_nohz_init检查tick_nohz_full_running状态通过tick_nohz_init_allCONFIG_NO_HZ_FULL_ALL下分配tick_nohz_full_mask并置全部位随后分配housekeeping_mask至少需要一个不做 NO_HZ 的处理器负责 timekeeping并用arch_irq_work_has_interruptx86 上检查cpu_has_apic确认架构支持 IPI 自唤醒。最后将当前处理器从tick_nohz_full_mask中清除它用于 timekeeping并对剩余处理器调用context_tracking_cpu_set开启上下文跟踪。动态定时器内核的软件定时器定时器概念与典型用法Linux 内核提供软件定时器software timer / dynamic timer概念允许内核函数在未来的某个时刻被调用广泛用于垃圾回收、协议超时等场景。例如net/netfilter/ipset/ip_set_list_set.c中list_set结构体的gc字段struct list_set { ... struct timer_list gc; ... };其初始化中设置回调与到期时间map-gc.function gc; map-gc.expires jiffies IPSET_GC_PERIOD(set-timeout) * HZ;init_timers定时器子系统的启动init_timers()kernel/time/timer.c在tick_init之后被调用包含四个步骤void __init init_timers(void) { init_timer_cpus(); init_timer_stats(); timer_register_cpu_notifier(); open_softirq(TIMER_SOFTIRQ, run_timer_softirq); }init_timer_cpus为每个 possible CPU 初始化tvec_baseinit_timer_stats初始化 per-CPU 的tstats_lookup_lock自旋锁保护/proc/timer_stats统计数据timer_register_cpu_notifier在CONFIG_HOTPLUG_CPU下注册 CPU 热插拔通知处理器下线时经timer_cpu_notify调用migrate_timers迁移定时器open_softirq(TIMER_SOFTIRQ, run_timer_softirq)注册软中断处理函数——动态定时器不在硬件中断上下文直接处理耗时操作而是推迟到软中断执行。tvec_base分层定时器轮timer wheeltvec_base是每个处理器动态定时器的主数据结构struct tvec_base { spinlock_t lock; struct timer_list *running_timer; unsigned long timer_jiffies; unsigned long next_timer; unsigned long active_timers; unsigned long all_timers; int cpu; bool migration_enabled; bool nohz_active; struct tvec_root tv1; struct tvec tv2; struct tvec tv3; struct tvec tv4; struct tvec tv5; } ____cacheline_aligned;字段含义timer_jiffies是最早到期时间用于定位已过期定时器next_timer在 NO_HZ 模式下为下一次中断保存下一个待处理定时器active_timers统计不可延迟定时器all_timers统计全部定时器migration_enabled与nohz_active分别表示定时器迁移能力与 NO_HZ 状态。最后五个字段构成经典的分层定时器轮。tv1的元素个数由TVR_SIZE决定而TVR_BITS依赖CONFIG_BASE_SMALL#define TVR_SIZE (1 TVR_BITS) #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)CONFIG_BASE_SMALL若启用可缩小内核数据结构默认关闭时tv1有 256 个槽位。tv1存放将在接下来 255 次中断内到期的定时器tv2/tv3/tv4/tv5分别存放2^14-1、2^20-1、2^26及更长到期周期的定时器。定时器运行机制run_timer_softirqrun_timer_softirq比较当前jiffies与base-timer_jiffies若当前时间已到则调用__run_timers在持锁状态下循环执行已到期定时器。核心是计算tv1索引index base-timer_jiffies TVR_MASK若索引为 0则通过cascade函数将上层tv2~tv5的定时器逐级级联下来随后递增timer_jiffies用hlist_move_list移出该槽位链表并逐个调用call_timer_fn执行回调fn(data)。动态定时器 API 速查使用动态定时器需定义timer_list变量两种初始化方式#define init_timer(timer) \ __init_timer((timer), 0) #define TIMER_INITIALIZER(_function, _expires, _data) \ __TIMER_INITIALIZER((_function), (_expires), (_data), 0)启动与停止void add_timer(struct timer_list *timer); int del_timer(struct timer_list *timer);clockevents 框架时钟源的概念反转框架定位正如文档所述Clock events are the conceptual reverse of clock sources。clocksource框架负责提供时间线把计数器转换为纳秒等单位而clockevents框架负责管理能够在未来某个确定时刻触发事件中断的时钟事件设备。clock_event_device 结构与状态机核心结构为include/linux/clockchips.h中的clock_event_device包含name、event_handler、set_next_event、features等字段。通用 features#define CLOCK_EVT_FEAT_PERIODIC 0x000001 /* 可编程为周期性事件 */ #define CLOCK_EVT_FEAT_ONESHOT 0x000002 /* 仅触发一次事件 */x86_64 还有CLOCK_EVT_FEAT_C3STOP (0x000008)——设备在 C3 状态会停止工作。时钟事件设备状态机enum clock_event_stateCLOCK_EVT_STATE_DETACHED——未被框架使用所有设备注册时的初始状态CLOCK_EVT_STATE_SHUTDOWN——已断电CLOCK_EVT_STATE_PERIODIC——可编程为周期性事件CLOCK_EVT_STATE_ONESHOT——可编程为一次性事件CLOCK_EVT_STATE_ONESHOT_STOPPED——曾编程为一次性事件、当前临时停止。设备注册流程以 at91sam926x 周期间隔定时器PIT为例初始化clock_event_device后调用clockevents_register_device(data-clkevt)。注册函数kernel/time/clockevents.c流程如下clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED)设置初始状态校验dev-cpumask为空则取smp_processor_id()对应处理器在raw_spin_lock_irqsave(clockevents_lock, flags)保护下list_add(dev-list, clockevent_devices)加入全局设备链表tick_check_new_device(dev)检查新设备是否优于当前 tick 设备tick_check_preferred中 oneshot 特性优先其次比较 rating 与 cpumask若更优则clockevents_exchange_device交换并tick_setup_device按模式调用tick_setup_periodic/tick_setup_oneshotclockevents_notify_released()清理已释放设备。其中tick_setup_periodic调用clockevents_switch_state(dev, CLOCK_EVT_STATE_PERIODIC)与clockevents_program_event__clockevents_switch_state依据目标状态分发到设备回调例如 PIT 的pit_clkevt_set_periodic会向AT91_PIT_MR寄存器写入(cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN置位 24、25 位以启用周期中断。x86_64 的三大时钟源HPET、ACPI PM 与 TSC通过 sysfs 与 dmesg 可观察 x86_64 平台上按初始化顺序注册的三个高分辨率时钟源$ dmesg | grep clocksource [ 0.000000] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 133484882848 ns [ 0.186498] clocksource: Switched to clocksource hpet [ 0.196827] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns [ 1.413685] tsc: Refined TSC clocksource calibration: 3999.981 MHz [ 2.413748] clocksource: Switched to clocksource tscHPETrating 250x86 的 HPET 实现位于arch/x86/kernel/hpet.c。start_kernel中late_time_initx86 上为x86_late_time_init依次调用x86_init.timers.timer_init()与tsc_init()触发初始化。hpet_time_init若hpet_enable()失败则回退到setup_pit_timer()最后setup_default_timer_irq()配置 IRQ0。hpet_enable检查内核命令行未传hpetdisable、确认 ACPI HPET 表提供的hpet_address后用ioremap_nocache(hpet_address, HPET_MMAP_SIZE)映射 1024 字节寄存器空间。其 clocksource 定义为static struct clocksource clocksource_hpet { .name hpet, .rating 250, .read read_hpet, .mask HPET_MASK, .flags CLOCK_SOURCE_IS_CONTINUOUS, .resume hpet_resume_counter, .archdata { .vclock_mode VCLOCK_HPET }, };read_hpet直接读取 Main Counter Register 返回原子计数器。ACPI PM timerrating 200实现位于drivers/clocksource/acpi_pm.c经 fs initcall 进入init_acpi_pm_clocksource。它依赖pmtmr_ioport由arch/x86/kernel/acpi/boot.c的acpi_parse_fadt从 FADT 表的X_PM_TMR_BLK字段解析得到。寄存器为 32 位运行计数read_pmtmr()通过inl(pmtmr_ioport) ACPI_PM_MASK读取低 24 位。其 clocksource 定义 rating 为 200static struct clocksource clocksource_acpi_pm { .name acpi_pm, .rating 200, .read acpi_pm_read, .mask (cycle_t)ACPI_PM_MASK, .flags CLOCK_SOURCE_IS_CONTINUOUS, };TSCrating 300最终胜出实现位于arch/x86/kernel/tsc.c。tsc_init先检查cpu_has_tsc展开为boot_cpu_has(X86_FEATURE_TSC)随后calibrate_tsc通过 MSR、PIT 等方式校准频率并为所有可能处理器初始化cyc2ns_init与set_cyc2ns_scale。实际注册推迟到 device initcall 阶段的init_tsc_clocksource以确保 TSC 在 HPET 之后注册TSC 需先经 HPET 校验。定义static struct clocksource clocksource_tsc { .name tsc, .rating 300, .read read_tsc, .mask CLOCKSOURCE_MASK(64), .flags CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_MUST_VERIFY, .archdata { .vclock_mode VCLOCK_TSC }, };由于 rating 最高300TSC 最终被选为当前时钟源。TSC 频率与处理器状态无关恒定速率递增可在/proc/cpuinfo中查看model name对应的标称频率。时钟相关的系统调用从用户态到内核用户程序同样需要时间。本章最后一部分以gettimeofday、clock_gettime、nanosleep三个系统调用为例追踪从 glibc 标准库到内核实现的完整路径仅讨论 x86_64。以最简单的gettimeofday为例#include time.h #include sys/time.h #include stdio.h int main(int argc, char **argv) { char buffer[40]; struct timeval time; gettimeofday(time, NULL); strftime(buffer, 40, Current date/time: %m-%d-%Y/%T, localtime(time.tv_sec)); printf(%s\n, buffer); return 0; }struct timeval包含tv_sec秒与tv_usec微秒。关键点在于gettimeofday并非普通系统调用——glibc 的实现sysdeps/unix/sysv/linux/x86/gettimeofday.c优先通过_dl_vdso_vsym解析 vDSO 中的__vdso_gettimeofday符号失败才回退到常规系统调用路径return (_dl_vdso_vsym (__vdso_gettimeofday, linux26) ?: (void*) (__gettimeofday_syscall));vDSO 入口定义于arch/x86/entry/vdso/vclock_gettime.c其中gettimeofday是__vdso_gettimeofday的弱别名后者在timeval非空时调用do_realtime完成当前时间读取。借助 vDSO 机制用户态可无陷入trap地读取时间这正是时钟源archdata.vclock_modeVCLOCK_TSC / VCLOCK_HPET与 vDSO 协同的价值所在。总结与继续阅读指引至此时间管理子系统的完整脉络已清晰可见jiffies提供 tick 计数基础clocksource统一抽象各类硬件计数器并支持按 rating 择优切换tick broadcast与dyntick/NO_HZ让空闲处理器摆脱周期性中断、兼顾功耗与唤醒动态定时器基于分层定时器轮timer wheel在软中断中批量执行到期回调clockevents框架管理能在未来时刻触发中断的时钟事件设备x86_64的 HPET、ACPI PM、TSC 三个时钟源按初始化顺序注册并逐级切换用户态通过系统调用或 vDSO 获取时间与上述内核抽象环环相扣。继续深入研究可依次阅读 linux-timers-1.md 至 linux-timers-7.md 七篇连载其中每一篇都附有对应的内核源码文件路径也可对照 翻译状态说明 了解各篇翻译进度。本章内容与 初始化章节setup_arch、start_kernel调用顺序、中断章节软中断与 IRQ 处理以及 CPU 概念章节cpumask、per-CPU 变量相互印证推荐交叉阅读以建立全局视角。赞分享【免费下载链接】linux-insides-zhLinux 内核揭秘项目地址https://gitcode.com/hust-open-atom-club/linux-insides-zh点击查看免费下载相关推荐内核如何度量时间Linux 内核揭秘linux-insides-zhclocksource、clockevents 与定时器框架详解内核如何度量时间Linux 内核揭秘linux insides zhclocksource、clockevents 与定时器框架详解 这篇文章基于开源项目Linux内核定时器与时间管理x86架构时钟源深度解析Linux内核定时器与时间管理x86架构时钟源深度解析 引言 在Linux内核的时间管理子系统中时钟源clocksource扮演着至关重要的角色。本文将文档教程操作系统Linux 内核定时器与时间管理深入解析 clocksource 框架Timers/linux-timers-2 精读Linux 内核定时器与时间管理深入解析 clocksource 框架Timers/linux timers 2 精读 本文是《Linux 内核揭秘》l上一篇Zoom 集成故障排查指南利用 knowledge-work-plugins 的 /debug-zoom 技能分层定位并修复问题下一篇fp-ts与GraphQL使用io-ts验证GraphQL查询结果创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考