sched_clock
[toc] kernel/time/sched_clock.c 调度器时钟(Scheduler Clock) 高性能的调度与追踪时间戳历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/time/sched_clock.c 提供的核心功能 sched_clock() 是为了解决内核中一个对性能极其敏感的需求:以极低的开销,获取一个高分辨率、单调递增的时间戳。 jiffies 虽然开销低,但其分辨率太差(毫秒级),完全无法满足现代调度器的需求。特别是对于CFS(完全公平调度器),它需要精确地知道一个任务在CPU上到底运行了多少纳秒,以便公平地更新其虚拟运行时间(vruntime)。如果时间测量不准,CFS的公平性就无从谈起。 此外,内核内部的其他高性能子系统也需要类似的时间戳: 性能追踪与分析:像ftrace和perf这样的工具,在记录内核事件时,需要为每个事件打上一个极其精确的时间戳,以便分析微秒甚至纳秒级的性能瓶颈。 锁竞争分析:内核的锁调试器需要精确测量一个任务在等待一个自旋锁上花费了多长时间。 sched_clock() 就是为了满足这些...
mutex
[toc] kernel/locking/mutex.c 互斥锁(Mutex) 内核中基本的睡眠锁实现历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/locking/mutex.c 实现的互斥锁(Mutex,Mutual Exclusion)是为了解决多任务内核中一个最基础、最普遍的并发控制问题:如何确保一段代码(临界区)在任何时刻最多只能被一个执行绪(线程或进程)执行,从而保护共享数据的完整性。 在没有互斥机制的情况下,如果多个CPU上的任务同时访问和修改同一个共享数据(如一个链表),就会导致数据损坏、状态不一致、内存泄漏等各种灾难性的后果。 mutex被设计为一种睡眠锁(Sleeping Lock),专门用于解决**进程上下文(Process Context)**中的互斥问题。它的诞生是为了与另一种锁——**自旋锁(Spinlock)**形成互补: 自旋锁适用于中断上下文或保护极短的、不容许睡眠的临界区。获取不到锁的任务会“自旋”(忙等待),浪费CPU。 如果临界区比较长,或者在临界区内需要调用可能导致睡眠的函数(如kmalloc(GFP...
time
[TOC] include/linux/ktime.hktime_set 从秒/纳秒值设置ktime_t变量123456789101112131415161718192021222324252627/** * ktime_set - 从秒/纳秒值设置ktime_t变量 * @secs:秒设置 * @nsecs:纳秒设置 * * 返回:值的ktime_t表示形式。 */static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs){ if (unlikely(secs >= KTIME_SEC_MAX)) return KTIME_MAX; return secs * NSEC_PER_SEC + (s64)nsecs;}/* Subtract two ktime_t variables. rem = lhs -rhs: */#define ktime_sub(lhs, rhs) ((lhs) - (rhs))/* Add two ktim...
timekeeping
[toc] kernel/time/timekeeping.c 内核时间保持(Kernel Timekeeping) 维护系统时间的核心与灵魂历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了解决操作系统中最基础、最核心的需求之一:以一种精确、稳定、单调的方式来跟踪和维护时间的流逝。 kernel/time/timekeeping.c所管理的时间保持子系统,具体解决了以下几个关键问题: 时间的表示与更新:需要一个核心机制来管理系统的“官方时间”。这包括“墙上时间”(Wall Time,即CLOCK_REALTIME,自1970年Epoch以来的时间,可以被用户或NTP修改),以及“单调时间”(Monotonic Time,即CLOCK_MONOTONIC,从系统启动开始单调递增,不受时间调整影响)。 时钟源的抽象:硬件提供了各种各样的时间源(Clock Sources),例如TSC(CPU的时间戳计数器)、HPET(高精度事件定时器)、ACPI PM Timer等。这些时钟源的精度、稳定性和访问速度各不相同。时间保持子系统需要一个框架来抽象这些...
timer
[toc] kernel/time/timer.c 传统内核定时器(Legacy Kernel Timers) 基于jiffies的通用定时机制历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/time/timer.c 实现了Linux内核中最传统、最通用的低分辨率定时器机制。它的诞生是为了解决内核中一个无处不在的需求:以一种低开销、非阻塞的方式,安排一个函数在未来的某个时间点被执行。 在内核的许多代码路径中,尤其是在与硬件交互时,都需要处理超时。例如: 设备驱动:一个驱动向设备发送一个命令后,不能无限期地等待其响应。它需要设置一个超时,如果在指定时间内没有收到响应,就必须进行错误处理。 网络协议栈:TCP协议在发送一个数据段后,会启动一个重传定时器。如果在规定时间内没有收到对方的确认(ACK),定时器到期后就会重新发送该数据段。 周期性轮询:某些简单的驱动可能需要周期性地检查硬件状态。 timer.c 提供的struct timer_list接口,就是为了满足这些**对精度要求不高(毫秒级)**的通用定时需求而设计的。 它的发展经历了哪些重...
tick
[toc] kernel/time/tick-*.c 内核时钟滴答(The Kernel Tick) 驱动时间流逝与进程抢占历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/time/tick-*.c 目录下的文件集合构成了内核时钟滴答(Kernel Tick)的底层实现。这项技术是所有分时操作系统的心跳(Heartbeat),它的诞生是为了解决两个最根本的问题: 时间流逝的度量:内核需要一个机制来驱动内部的时间概念。没有一个周期性的“滴答”,像jiffies这样的计数器将无法更新,基于jiffies的传统定时器(timer_list)也将永远不会到期。 强制性进程抢占(Preemptive Multitasking):在一个协作式多任务系统中,一个进程会一直运行直到它自愿放弃CPU。这会导致一个死循环的进程就能锁死整个系统。为了实现抢占式多任务,内核需要一个周期性的、不可抗拒的事件来中断当前正在运行的进程,并给调度器一个机会去检查是否有其他进程应该运行。这个事件就是时钟滴答中断。 简而言之,内核滴答是调度器得以强制执行时间片轮转和内核传统时...
deadline
[toc] kernel/sched/deadline.c 截止时间调度器(Deadline Scheduler, SCHED_DEADLINE) 面向硬实时的可预测调度历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/sched/deadline.c 实现了SCHED_DEADLINE调度策略,它的诞生是为了解决传统实时调度器(SCHED_FIFO/RR)在硬实时(Hard Real-time)和复杂系统中所面临的局限性。 SCHED_FIFO/RR基于静态优先级,虽然模型简单,但在复杂系统中存在两个主要问题: 缺乏可分析性(Analyzability):在一个包含几十个实时任务的系统中,仅仅依靠手动分配静态优先级来保证所有任务都能满足各自的截止时间,是一项极其困难且易错的工作。当任务间存在复杂的依赖关系时,几乎无法从理论上证明系统的可调度性。 任务间无隔离:SCHED_FIFO是“赢家通吃”模型。一个有bug或行为不当的高优先级任务可以无限期地运行,完全饿死所有低优先级任务,导致系统服务完全中断。它不提供任何形式的“带宽...
idle
[toc] kernel/sched/idle.c 空闲调度(Idle Scheduling) CPU无事可做时的最终选择历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/sched/idle.c 的实现是为了解决一个操作系统中最基础、最本质的问题:当CPU上没有任何有意义的工作(没有可运行的进程或内核线程)时,CPU应该做什么? 一个CPU不能简单地“停止”,它必须始终在执行指令。因此,系统必须提供一个“最后的选择”——一个特殊的任务,在所有其他任务都无法运行时来占用CPU。这个任务就是空闲任务(Idle Task)。 然而,仅仅让CPU执行一个空、、循环(while(1);)是远远不够的,这会带来一个巨大的新问题:功耗。一个在循环中空转的CPU会以最高速度运行,消耗大量电力,产生大量热量,这对于任何设备(尤其是移动设备)都是不可接受的。 因此,idle.c 的核心目标有两个: 提供一个默认的执行流,确保CPU永远有事可做。 实现极致的节能,通过将空闲的CPU置于深度睡眠的低功耗状态来节省能源。 它的发展经历了哪些重要的里程碑或版本迭代?L...
jiffies
[toc] kernel/time/jiffies.c 内核心跳(Kernel Heartbeat) 低分辨率定时器的基础历史与背景这项技术是为了解决什么特定问题而诞生的?jiffies 是Linux内核中最古老、最基础的时间测量机制。它的诞生是为了解决内核内部需要一个**简单、廉价、全局统一的“心跳”或“滴答(tick)”**来驱动各种基于时间的活动。 在操作系统内核中,大量活动都不是由外部事件触发,而是需要在一个相对的时间点后发生。例如: 超时(Timeouts):一个网络驱动发送了一个数据包,它需要在一个超时时间(如200毫秒)后检查是否收到了确认。 调度(Scheduling):一个SCHED_RR(轮转)策略的进程,其运行时间片用完后需要被抢占。 周期性任务(Periodic Tasks):某些内核任务需要周期性地运行。 简单的延迟(Delays):代码中需要一个短暂的、非精确的延迟。 jiffies 提供了一个极其简单的解决方案:它是一个在系统启动后不断递增的全局计数器。通过读取这个计数器的值,内核的任何部分都可以获得一个关于“时间流逝”的基本...
fair
[toc] kernel/sched/fair.c 完全公平调度器(Completely Fair Scheduler, CFS) Linux默认的普通进程调度策略历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/sched/fair.c 是Linux内核**完全公平调度器(Completely Fair Scheduler, CFS)**的核心实现。它的诞生是为了彻底取代在它之前的O(1)调度器,并解决其固有的复杂性和公平性问题。 O(1)调度器虽然调度决策速度快,但它依赖于一套非常复杂的、启发式的算法来“猜测”一个进程是否是“交互式”的,并动态地调整其优先级。这导致了以下问题: 公平性不足:其启发式算法并不完美,常常导致某些进程获得不公平的CPU时间份额。 代码复杂难懂:包含大量“魔法数字”和复杂的逻辑,难以维护和调试。 可调优性差:nice值对进程行为的影响不直观,难以预测。 CFS的出现,旨在用一个极其简单、优雅且可证明的公平模型来取代这一切。其核心目标不再是使用复杂的技巧去追踪进程行为,而是去模拟一个**“理想的、完美多任务的CPU...