1. 调度概述:什么是进程调度?调度器的角色与位置

说到操作系统,调度这事儿,我估计是每个搞底层开发的人都绕不开的坎儿。

进程调度,说白了就是操作系统决定「下一个该谁上CPU跑」的过程。你想想看,一台电脑可能同时开着浏览器、IDE、音乐播放器,但CPU核心就那么几个。谁先跑?谁后跑?跑多久?这就是调度要解决的问题。

1.1 调度器的核心角色

调度器(Scheduler)是操作系统内核里的一个关键模块。它的任务很简单——在多个就绪进程之间,选一个出来执行

我个人习惯把调度器比作「CPU的分配官」。它手里拿着一个名单(就绪队列),每次CPU空闲了,它就从名单里挑一个人进去干活。

调度器的三个核心职责:

  • 选择:从就绪队列中选一个进程
  • 切换:保存当前进程的上下文,恢复新进程的上下文
  • 分配:把CPU时间片分配给选中的进程

嗯,这里要注意一点。调度器不是一直在运行的。它只在特定时机被触发——比如进程主动让出CPU、时间片用完、或者有更高优先级的进程醒来。

1.2 调度器在系统中的位置

调度器到底待在哪儿?我画了一张图,你看一眼就明白了。

用户进程层 进程A 进程B 进程C 进程D 操作系统内核 调度器 (Scheduler) 选择下一个执行的进程 就绪队列 等待队列 CPU 核心 调度器

从图上你能看到,调度器位于内核层,夹在用户进程和CPU之间。它手里管着两个关键队列:就绪队列(等着上CPU的)和等待队列(在等I/O或其他资源的)。

1.3 调度发生的时机

调度器什么时候干活?我总结了一下,主要有这么几个时机:

触发时机 说明 常见场景
进程主动阻塞 进程等待I/O或资源 read()、sleep()
时间片耗尽 进程用完了分配的CPU时间 时钟中断触发
进程主动让出 进程调用yield() 用户态主动放弃
高优先级进程就绪 优先级更高的进程被唤醒 中断处理完成
进程终止 当前进程执行完毕 exit()调用

一个小经验:我在做嵌入式系统时发现,很多人以为调度只在时间片用完时才发生。其实不是。进程主动让出CPU的情况非常常见,尤其是在I/O密集型的应用里。你写一个网络服务器,大部分时间进程都在等网络数据,这时候调度器频繁介入,选别的进程上CPU。

1.4 调度器的两种工作模式

调度器干活的方式,其实就两种:

  • 非抢占式调度:进程自己决定什么时候让出CPU。它不跑完或者不主动阻塞,别人就别想上。
  • 抢占式调度:操作系统有「强制手段」。时间片到了,或者有更紧急的进程来了,直接把你踢下去。

这两种模式的区别,我后面会专门展开讲。这里先记住一个核心点:非抢占式靠自觉,抢占式靠制度

注意:我曾经在一个实时系统项目里吃过亏。当时用了非抢占式调度,结果有个进程写了个死循环,整个系统直接卡死。从那以后,我对非抢占式调度就多留了个心眼——它简单,但风险也大。

1.5 调度器与上下文切换

调度器选好下一个进程后,还得干一件事——上下文切换

说白了,就是把当前进程的「现场」保存下来(寄存器、程序计数器、栈指针等),再把新进程的「现场」恢复上去。这个过程是有开销的,我见过一些优化不好的系统,光上下文切换就占了CPU时间的10%以上。

// 上下文切换的伪代码示意
void context_switch(PCB *current, PCB *next) {
    // 保存当前进程的上下文
    save_registers(current->context);
    save_stack_pointer(current->context);
    save_program_counter(current->context);
    
    // 切换到内核栈
    switch_kernel_stack(next);
    
    // 恢复新进程的上下文
    restore_registers(next->context);
    restore_stack_pointer(next->context);
    restore_program_counter(next->context);
    
    // 跳转到新进程执行
    jump_to_user_mode(next);
}

你看这段代码,虽然只有几行,但每次切换都要做这些操作。所以调度频率不能太高,否则CPU全花在切换上了。但也不能太低,否则响应太慢。这个平衡,就是调度器设计的核心难题。

1.6 小结

进程调度,说白了就是操作系统里那个「谁上谁下」的决策机制。调度器是执行者,它站在内核层,盯着就绪队列,随时准备把下一个进程送上CPU。

我个人觉得,理解调度器的位置和角色,是搞懂整个调度系统的第一步。你想想看,没有调度器,进程之间就是一片混乱——谁抢到CPU谁跑,那系统还怎么稳定?

嗯,这一章就到这里。调度器的基本概念清楚了,后面我们再深入看看它具体怎么选、怎么切。


公众号:蓝海资料掘金营,微信deep3321