中断、时钟与轮转调度(Round-Robin)
本节目标
- 理解中断如何"打断" CPU 当前工作
- 手写时钟中断驱动的 Round-Robin 调度器
- 体会"多任务"是如何被"伪并行"出来的
中断(Interrupt):硬件/时钟发信号给 CPU,CPU 暂停当前任务、跳去处理中断,处理完再回来。时钟中断是"多任务"的节拍器。
// 运行环境:Node.js 14+
// 保存为 aj-l12.js,执行:node aj-l12.js
class Scheduler {
constructor(quantum = 2) {
this.queue = [] // 就绪队列
this.tick = 0
this.quantum = quantum // 每个任务运行几个时钟周期
}
add(task) { this.queue.push({ name: task, used: 0 }) }
// 时钟中断:每次 tick 推进,到时间片则抢占
onClock() {
if (!this.queue.length) return
const cur = this.queue[0]
cur.used++
console.log(`tick ${this.tick}: 运行 ${cur.name} (${cur.used}/${this.quantum})`)
this.tick++
if (cur.used >= this.quantum) {
cur.used = 0
this.queue.shift() // 出队
this.queue.push(cur) // 排到队尾(轮转)
console.log(` → 时间片到,${cur.name} 让出 CPU`)
}
}
}
// 调用示例:3 个任务轮流跑
const s = new Scheduler(2)
s.add('A'); s.add('B'); s.add('C')
for (let i = 0; i < 12; i++) s.onClock()轮转(RR):每个任务跑一个固定时间片,时间到就排到队尾,下一个上。宏觉上"所有程序同时跑",实则是时钟中断在快速切换——单核 CPU 的"伪并行"。
名词解释
- 中断(Interrupt):外部/内部事件打断 CPU 当前执行流、强制跳转去处理程序的机制。时钟中断是操作系统的心跳。
- 时间片(Time Quantum):调度器分给每个任务连续运行的时长;用完即被抢占,保证公平。
- 轮转调度(Round-Robin):就绪任务排成环,依次给时间片运行,到时让出排到队尾。简单公平,适合分时系统。
课后练习
- 如果没有时钟中断,单核能"同时"跑多个程序吗?
- 答案:不能。没有时钟强制切换,一个程序不主动让出 CPU 就会一直占着,其他程序饿死;时钟中断是抢占式多任务的基石。
- RR 调度时间片设太长或太短分别有什么问题?
- 答案:太长→响应慢、像批处理;太短→切换开销占比高、吞吐量下降。需按任务特性权衡。
总结
手写 RR 调度器,是把"多任务"从玄学变成可计算模型的一课。你会恍然大悟:所谓"电脑同时跑几十个程序",在单核上根本不是真并行,而是时钟中断这个"节拍器"在毫秒级快速切换,让每个程序都觉得自己独占 CPU。中断是这一切的总开关——没有它,一个死循环就能卡死全机。我特别想强调"时间片"这个权衡艺术:太长响应迟钝,太短切换耗尽算力。真实操作系统(Linux CFS、Windows)的调度比 RR 复杂得多,但"公平分配 CPU 时间 + 可抢占"的核心思想一脉相承。理解调度,你看任务管理器里每个进程"占用 CPU 百分比"、看 nice 值调优先级,就都知道背后是同一套"谁该上、上多久"的决策。这是从"会用电脑"到"懂电脑"的分水岭。