等待队列、睡眠与唤醒

这页讲的是:任务等不到资源时,Linux 并不是让它傻站着浪费 CPU,而是把它放进等待关系里先睡下,等条件满足再叫醒。学这页的重点,是理解“等待”在内核里不是消极停住,而是一套被认真组织起来的调度与同步行为。

这块是什么

等待队列、睡眠与唤醒,讲的是当任务暂时做不下去时,内核如何把它挂到某个等待条件上,让它先退出运行竞争,等资源可用、事件发生或条件改变后,再把它重新唤醒继续推进。这是内核把“我现在做不了”变成“我等合适时机再继续”的关键组织方式。

可以把它理解成:不是所有人都站在窗口前死等叫号,而是先去候场区坐下,等系统通知到你时再回来处理。

它负责什么

让任务优雅等待

  • 资源暂时不可用时先别白耗 CPU
  • 把任务从当前运行竞争里拿下来
  • 让等待变成有条件、有组织的状态
  • 避免用忙等把系统拖慢

建立唤醒关系

  • 把“谁在等什么”组织清楚
  • 条件满足时把对应任务叫醒
  • 让事件和任务推进重新接上
  • 把等待和恢复运行做成一条闭环路径

衔接调度与同步

  • 等待不是单独动作,而会影响调度
  • 唤醒时机也常与锁和状态变化绑定
  • 很多阻塞式接口都离不开它
  • 让任务等待不至于变成时序混乱

为什么不能一直忙等

如果一直忙等会怎样等待队列的价值
任务一直反复检查条件会白白烧 CPU,影响系统整体吞吐。条件不满足时先让出 CPU,更符合系统整体利益。
大家都挤在前台等待调度器会被很多“其实干不了活”的任务干扰。让真正能推进的任务先运行。
等待和事件没有正式关系谁该被叫醒、何时叫醒会变得混乱。把等待对象和唤醒时机组织成明确关系。
阻塞路径全靠手写时序更容易出现遗漏唤醒、早唤醒或状态错乱。提供统一世界观来组织睡眠与唤醒。

关键概念

概念现在怎么理解
等待队列把等待某个条件的任务组织起来的那套机制。
睡眠任务暂时退出运行竞争,等待未来某个条件成立。
唤醒条件满足后,把原先等待的任务重新拉回可运行世界。
阻塞当前做不下去,只能等资源或事件到来的状态。
条件变化真正决定“该不该叫醒任务”的那个状态改变点。

为什么重要

常见误解

它不负责什么

和其他模块的关系

相关模块关系
调度器任务睡下去和被唤醒,本质上都会改变调度器眼里的可运行任务集合。
并发控制等待前后常要和状态修改、锁保护一起配合,避免错过唤醒。
定时器 / 超时很多等待不是无限等,而要配合超时和延迟执行一起工作。
驱动 / I/O 路径设备未准备好、数据未到、资源未释放时,经常都要先睡再等唤醒。

一条典型“先睡再醒”路径现在怎么想

步骤发生了什么最容易踩的坑
先检查条件任务先确认现在到底能不能继续推进。如果条件判断和后续睡眠没配好,就可能错过刚发生的变化。
挂入等待关系当前任务被正式放进等待队列,准备退出运行竞争。如果只是“心里想等”却没被系统正式组织起来,后面就没人知道该叫醒谁。
条件发生变化别的路径释放资源、收到数据或推进状态。这一步如果没和状态更新顺序配好,就容易出现遗漏唤醒。
唤醒并重新竞争 CPU任务被拉回可运行集合,之后仍要等待调度器真正安排它继续跑。被唤醒不等于立刻执行,这也是很多人最容易混的地方。

读完这页后,你应该能回答

后面适合继续问:等待队列和 poll/select 这类等待模型是什么关系?为什么遗漏唤醒会让问题显得特别随机?超时等待为什么又会把定时器拉进来?