第二批复习总结.md 11 KB

第二批 FreeRTOS / RTOS 八股 · 复习总结(8 主题)

使用说明:先自测「判别规则速查表」,遮住右列自答;再做「综合练习题」,最后对答案。 面试前只翻本目录,不背题。


一、判别规则速查表(遮右自测)

# 主题 一句话判别规则
24 任务状态机 在跑=Running;排队等 CPU=Ready;主动等事件/延时=Blocked(自动醒、有超时);被外部挂起=Suspended(手动醒、无超时)
25 抢占 vs 时间片 高优先级就绪→抢占(跨级);同优先级 tick 到点→时间片;低优先级就绪→永不切换
26 优先级反转 高等待 + 低持有 + 中插队(三者齐)= 反转;解决=互斥量(优先级继承),别拿二值信号量当锁
27 临界区 数据被中断/硬件碰→关中断(临界区);只被任务碰→互斥量/挂起调度器;临界区禁阻塞、要短、多核只关本核
28 IPC 选型 数据→队列;事件→信号量;资源→互斥量;多事件组合→事件组;一对一简单→任务通知
29 RTOS 任务同步方式 一对一→任务通知;多条件组合(AND/OR)→事件组;计数/资源/多接收者→信号量
30 ISR 通信 会阻塞或要任务身份(互斥量)→ ISR 禁用;其余发送/通知一律 FromISR 版
31 栈估算 栈 =最坏路径峰值(局部+调用帧+库函数+中断嵌套)× 1.5~2;HighWaterMark 留 20%+ 余量

二、易混对比集中营(高频考点串讲)

任务四种状态

Blocked Suspended
原因 主动等待事件(延时/信号量/队列) 被外部挂起
恢复 事件来了自动回 Ready 必须 vTaskResume
有超时吗

抢占 vs 时间片

抢占 时间片
触发 更高优先级就绪 tick 到点(同优先级)
作用 跨优先级 同优先级内部
目的 最高优先级先跑 公平轮流

二值信号量 vs 互斥量

二值信号量 互斥量
优先级继承
所有权 任何人可释放 只能获取者释放
用途 事件通知/同步 保护共享资源
反转风险 继承缓解

优先级继承 vs 优先级天花板

优先级继承 优先级天花板
机制 持锁者动态提到当前等待者水平 持锁者静态提到所有使用者最高级
优点 灵活、不过度 简单可靠
缺点 实现复杂、链式继承开销 过度提升,可能降整体实时性

临界区三件套

关中断(临界区) 挂起调度器 互斥量
挡什么 中断+任务 只挡任务 只挡任务(等待者阻塞)
中断响应 不能
适用 中断也碰的数据 只有任务碰 只有任务碰、要等锁
代价 中断延迟大 切换开销

IPC 五工具选型总表

工具 传什么 适用 成本
队列 数据 数据流、命令 中(复制)
信号量 事件/计数 通知、计数
互斥量 无(锁) 资源独占 低+继承
事件组 事件组合 多事件与/或
任务通知 简单信号 一对一唤醒 最低

普通 API vs FromISR 版

普通版 FromISR 版
阻塞吗 会(带超时) 不会(失败即返)
唤醒高优先级 立即切换 pxHigherPriorityTaskWoken,中断返回后才切换
适用 任务上下文 中断/任务都可用

栈 vs 堆

存放 局部变量/调用帧/保存寄存器 malloc 动态内存
谁管 系统自动 程序员
溢出后果 踩坏相邻内存/任务 分配失败/碎片

三、综合练习题(答完再对答案)

判断题(对/错 + 一句话理由)

  1. vTaskDelay(100) 之后,任务进入 Suspended 状态。答:错,是阻塞状态
  2. 一个任务被更高优先级任务抢占后,先进入 Ready 状态排队,不会直接回 Running。答:对,任务被更高优先级任务抢占后,先进入 Ready 状态排队,而不是阻塞和悬挂和运行。
  3. 两个同优先级任务轮流执行,一个的 tick 时间片用完换另一个跑——这叫抢占。答:错,是时间片轮换
  4. 任务 H(8) 等信号量 S,任务 L(2) 持有 S,任务 M(4) 就绪长跑 → 发生优先级反转。答:对,高优先级任务等待资源,低优先级任务持有资源,中优先级任务是就绪状态,不等待也不持有资源,发生优先级反转
  5. 任务 A(8) 等互斥量,B(2) 持互斥量,C(1) 就绪 → 发生优先级反转。答:错,高优先级任务等待资源,低优先级任务持有资源,中优先级任务是就绪状态,不等待也不持有资源,发生优先级反转
  6. 临界区里调用 vTaskDelay(10) 会正常工作,只是慢一点。答:错,临界区的本质是关闭中断,在临界区内的动作必须是微秒级别,一旦达到毫秒就会发生跑飞、死锁等, 调用vTaskDelay(10)进入阻塞,但计时器定时中断没正常工作,会发生错误。
  7. 数据同时被任务和中断访问时,用互斥量保护就够了。答:错,中断也要碰的数据,尽量还是要使用关中断(临界区)。
  8. 信号量可以把具体的数据值传给接收任务。答:错,不能,除非是计数任务等
  9. 经典版任务通知可以一次通知多个任务。答:错,不能,一般只能1对1通知
  10. ISR 里可以用带超时参数的 xQueueSend。答:错,临界区的本质是关闭中断,在临界区内的动作必须是微秒级别,一旦达到毫秒就会发生跑飞、死锁等。
  11. ISR 里可以给互斥量 give。答:错,互斥量要进行优先级继承,这会包含任务上下文。而在 ISR 里面只有中断上下文,不能够正常恢复现场,导致会跑飞。
  12. 任务栈开得越大越好,4096 words 保证永不溢出。答:错,会浪费资源
  13. uxTaskGetStackHighWaterMark 返回的值越大,表示栈越接近溢出。答:错,返回值表示占历史最低空闲资源,越大代表空闲的资源越多,越不接近溢出。
  14. RTOS 里任务正跑时被中断打断,异常帧会压进当前任务自己的栈。答:对,RTOS 任务跑在 PSP(任务自己的栈),中断异常帧压进当前任务栈——这就是估算要算中断嵌套的原因。

填空题

  1. 任务等待一个永不发生的事件,会永久处于 ____ 状态(RTOS 经典 bug)。答:饥饿
  2. 需要固定周期执行(硬实时周期任务),用 ____ 而非 vTaskDelay。答:vTaskDelayUnit
  3. 解决优先级反转的两个机制:____(FreeRTOS 默认)和 ____。答:优先级继承,优先级天花板
  4. 保护共享资源用 ____;事件通知用 ____(0/1 信号)。答:互斥量,任务通知
  5. ISR 里通知任务必须用 ____ 结尾的 API,通过 ____ 标志在中断返回后切换。答:FromISR,pxHigherPriorityTaskWoken(本质是pdTrue)
  6. 任务栈估算 = ____ × 余量系数(经验 1.5~2)。答:最坏路径峰值(局部变量+调用帧+库函数+中断嵌套)
  7. 串口收到一个字节的数据要交给另一个任务处理 → 用 ____。答:队列
  8. 等"按键按下 OR 定时器到点"任一事件 → 用 ____。答:事件组

场景 / 代码判断v

  1. 场景:高优先级任务被中优先级任务拖住,持有资源的低优先级任务一直抢不到 CPU。识别这是什么问题,并给出解决方案。答:优先级翻转,使用互斥量的优先级继承方案或者优先级天花板方案,一般而言采用优先级继承。
  2. 代码错在哪:void ISR(void) { xQueueSend(&q, &data, 10); }答:在中断中,ISR不能够使这个带阻塞的xQueueSend
  3. 代码会怎样:taskENTER_CRITICAL(); vTaskDelay(10); taskEXIT_CRITICAL();答:临界区的本质是关闭中断,在临界区内的动作必须是微秒级别,一旦达到毫秒就会发生跑飞、死锁等, 调用vTaskDelay(10)进入阻塞,但计时器定时中断没正常工作,会发生错误。
  4. 任务栈 128 words,uxTaskGetStackHighWaterMark 返回 20——栈要不要加大?答:用,余量系数计算得128*0.2=25.6,可知够,但任务功能需求加载时可能需要加

四、答案(已分离)

答案解析已单独存放,避免自测时不小心看到答案:

第二批复习总结-答案.md(同目录)——完成全部 26 题后再翻开对照。


复习目标:每条规则能自己讲出"为什么",不只记住结论。