60 秒回答模板

每个任务需要自己的栈,因为任务被切走时,它的函数调用链、局部变量、返回地址和中断返回现场都要保留。如果所有任务共用一个栈,任务 A 阻塞在某个函数深处后,任务 B 继续调用函数会覆盖 A 的局部变量和返回地址,A 再恢复就无法从原位置正确执行。FreeRTOS 的 TCB 会保存任务的栈顶指针、优先级、状态等信息。上下文切换时,硬件和软件一起保存当前任务的寄存器现场:Cortex-M 异常进入会自动压入 R0-R3、R12、LR、PC、xPSR 等,PendSV 再保存 R4-R11,必要时保存 FPU 上下文;然后把当前 PSP 存入 TCB,选下一个任务,恢复它的栈指针和寄存器。上下文还包括任务状态、临界区嵌套、通知值或 TLS 等内核管理信息。

考点 独立栈
难度 真实面经题
回答目标 说明自己理解任务独立执行现场和上下文切换保存恢复的必要性。

深入解析

01

栈保存函数执行现场

函数调用的返回地址、局部变量、保存寄存器和参数临时空间都在栈上。任务被阻塞时,这些内容必须保持不变,才能恢复到阻塞前的执行点。

02

共享一个栈会互相覆盖

多任务不是简单轮流调用函数。任务可能在任意嵌套深度被切出,如果另一个任务继续使用同一栈空间,原任务的调用链就被破坏。

03

TCB 记录任务身份和栈顶

任务控制块保存当前栈顶、优先级、状态、链表节点和其他调度信息。调度器通过切换 TCB 中的栈指针实现从一个任务切到另一个任务。

04

寄存器保存分硬件和软件

Cortex-M 异常机制自动保存一部分寄存器,移植层保存剩余 callee-saved 寄存器和可选 FPU 上下文。恢复时按相反顺序弹出,任务就像从未被打断一样继续执行。

易错点

  • 认为任务只是函数,轮流调用即可,不需要独立栈。
  • 只说保存 PC,不提通用寄存器、栈指针和返回现场。
  • 忽略任务阻塞在深层调用时局部变量必须保留。
  • 不区分硬件自动保存和移植层软件保存的上下文。

面试官追问

任务的全局变量也存在任务栈里吗?

不是。全局和静态变量在全局数据区,任务栈主要放局部自动变量、调用现场和部分上下文。

FPU 上下文什么时候需要保存?

任务使用浮点且端口启用 FPU 支持时需要保存或延迟保存浮点寄存器,否则任务切换后浮点计算会互相污染。

怎么验证这个 RTOS 方案没有引入新的实时性问题?

要看最坏响应时间、任务优先级、栈水位、队列积压、临界区时长和中断延迟,用压力用例和日志证明正常路径、阻塞路径、异常恢复路径都在预算内。