Skip to content

任务切换是怎么实现的

李述铜

1346字约4分钟

2025-08-30

本小节主要介绍RTOS是如何控制CPU在不同的任务之间执行。

任务运行的表现:并发而非并行执行

在多任务环境下,存在着多个while(1)的任务函数。虽然每个任务看上去都在持续运行,比如一个任务在不停闪灯,另一个在读取串口,还有一个在检测按键是否按下。

但实际上,由于CPU 只有一个,所以它在某一时刻只能执行一个任务。

那么,问题来了:多个任务是怎么“同时”工作的?

这就是RTOS的强大之处 —— 它让CPU在多个任务之间快速切换执行,每个任务轮流“占用”CPU,但切换得非常快(毫秒级甚至微秒级),人眼看起来就像所有任务都在同时运行一样。

alt text 这种有点像我们学习单片机控制多位数码管的操作。每次单片机只能控制一位数码管点亮。通过快速地轮流让每位数码管点亮,只要时间足够快,人眼就察觉不出来这种变量,以为所有数码管在同时点亮。

alt text综上所述,RTOS控制任务并发执行,而非并行执行。

  • 每个任务并不是从头运行到尾,而是运行一段就被暂停,等待下次继续
  • RTOS 负责在任务之间切换,让每个任务都能“轮到自己”使用 CPU
  • 切换过程非常快,用户感觉不到“换人”了,仿佛所有任务都在并行执行

RTOS是如何做到这一点的

原理

我们可以将该CPU看作是唯一的厨师,裸机开发中,他要一个人轮流完成煮汤、炒菜、接待顾客这些任务,工作全靠自己的安排(main中的while(1)循环)。

但在RTOS下,虽然仍然只有一个厨师(CPU),但你请了一个 “调度经理”(RTOS)。他会帮助你把这位厨师的时间合理分配到不同的工作上,让这些任务轮流执行,看起来像是同时在进行。

alt text 具体来说,RTOS通过以下方式来实现这种操作:

问题解决概念
厨师不能“同时做三件事”,那怎么办?“每次只做一件事,但每件事只做一小会儿,就换下一件!例如:每件事做 100 毫秒。”时间片轮转调度
那怎么记住上次做哪儿了?每次切换时,调度经理(RTOS)会:
+ 记住:工作进行到哪一步了(如炒菜炒到哪了)(保存状态)
+ 下一次切回来,就从上次离开的地方继续做(恢复状态)
保存和恢复上下文
那如果顾客突然进来怎么办?(需要优先处理)不管你在搅汤还是炒菜,只要顾客来了,立刻中断工作,去完成“接待顾客”的任务。接待完再回去继续炒菜或搅汤抢占式调度

简单来说,RTOS 通过“轮着做 + 紧急插队”的方式,让CPU看起来能同时应付多件事,做到像多个 while(1) 循环一样并发运行。实际上,RTOS通过控制CPU在它们之间快速切换执行来实现。

任务上下文

为了理解RTOS如何进行任务切换,我们需要理解什么是任务上下文。

相关信息

任务上下文是一个任务在某一时刻的运行现场信息,主要包括:

  • CPU 寄存器的值(如程序计数器PC、堆栈指针SP等)
  • 栈内容(函数调用临时数据、返回地址等)
  • 任务状态信息(运行、就绪、挂起等)

我们可以把“任务上下文”理解为:一张保存了当前任务执行现场的“快照”,便于以后能原样“恢复”运行。

为什么需要这些东西?原因在于:RTOS 中有多个任务轮流执行,但 CPU 只有一个,所以当系统从一个任务切换到另一个任务时:

  • 不能丢失当前任务的运行状态
  • 要能够恢复另一个任务的运行状态

也就是说,我们要保存这些运行状态,以便CPU从某个任务切换出去执行其它任务,再切换回来时,该任务能够继续从原来暂停执行的位置继续往下运行。这些运行状态,保存在任务的上下文。

alt text

切换过程

当需要进行任务切换时,整个切换流程如下:

  1. 保存当前任务上下文(寄存器 + 堆栈指针)
  2. 调度器选择一个新任务
  3. 加载新任务的上下文
  4. CPU 继续执行新任务

什么时候触发切换

具体来说,当发生以下情况时,RTOS会触发任务切换,从而进行上下文切换:

  • 主动让出 CPU(如延时)
  • 更高优先级任务就绪(抢占)
  • 调度器强制切换(时间片到)