面灵AI→

诺瓦星云嵌入式一面:FreeRTOS 调度、C++ 继承与 STL 容器

轮次
一面
时间
2026-09
来源
牛客网

《面试题目》

  1. 自我介绍(2 分钟)。
  2. 讲一下项目里 FreeRTOS 的任务优先级、任务调度原理,有没有遇到过任务死锁?怎么排查?
  3. 线程是独立的吗?线程死锁的四个必要条件是什么?
  4. public、protected、private 三种继承的权限变化分别是怎样的?
  5. STL 容器怎么分类?vector 和 list 的区别是什么?deque 的底层结构是怎样的?
  6. map 与 unordered_map 的底层实现、优缺点分别是什么?
  7. 中断是什么?中断上下文能不能用 printf、能不能阻塞?
  8. C 和 C++ 的区别是什么?
  9. 你了解诺瓦星云吗?我们主要做什么产品?
  10. 反问:嵌入式岗位主要负责哪块,是偏底层驱动还是应用开发?团队主要做哪些产品相关固件,日常工作偏硬件外设驱动还是上层业务代码?

《参考解析》

FreeRTOS 的调度与死锁排查:它的任务优先级是数字越大优先级越高,内核默认抢占式调度——高优先级任务一旦就绪就立刻抢占当前任务,同优先级任务之间按时间片轮转。排查死锁的抓手是任务状态:先看有几个任务长期停在阻塞态、各自卡在哪个阻塞 API 上,再用任务列表与栈水位函数把现场打出来,顺着信号量、互斥量、队列的持有关系往下找环路。项目里常见的根因是两处获取顺序相反(A 先拿锁 1 再拿锁 2,B 反过来),统一全局申请顺序就能解掉;另一类是把互斥量用成了信号量,丢掉了优先级继承,于是表现为偶发卡顿而不是彻底卡死。

线程的私有与共享,以及死锁四个必要条件:同一进程内的线程共享地址空间、全局变量、堆和文件描述符,各自独立持有栈、寄存器现场和局部变量,切换不需要换页表,所以比进程轻。死锁的四个条件是互斥、请求与保持、不可剥夺、循环等待,四个同时成立才会死锁;因此破解方式就是打掉任意一条——把资源改成可共享、一次性申请全部资源、允许抢占,或者最常用的按固定顺序申请,破坏循环等待。

三种继承的权限变化:public 继承保持基类成员的可见性不变,基类的 public 仍是 public、protected 仍是 protected,private 成员始终不可直接访问;protected 继承把基类的 public 和 protected 都降为派生类的 protected;private 继承则把这两类都降为派生类的 private。记法上就是「继承方式决定了派生类里能见到的最高权限」,而基类 private 成员无论哪种继承方式都不能被派生类直接访问,只能通过基类的接口。

STL 容器的分类与序列容器选型:整体分四类——序列容器(vector、list、deque、array)、关联容器(set、map 及 multiset、multimap,底层红黑树)、无序关联容器(unordered_set、unordered_map,底层哈希表)、容器适配器(stack、queue、priority_queue,基于前面的容器封装接口)。vector 是连续内存的动态数组,随机访问 O(1)、尾插摊还 O(1),中间插入删除要搬元素;list 是双向链表,任意位置插入删除 O(1),但不支持随机访问、每个节点有额外指针开销、缓存局部性差。deque 是分段连续——若干固定大小的连续块加一张中控索引表,因此既支持 O(1) 随机访问,又能在首尾高效增删,代价是结构复杂、中间插入仍要搬数据。

map 与 unordered_map 怎么选:map 用红黑树,元素按 key 有序,查找插入删除稳定在 O(log n),支持范围查询和按序遍历,节点有额外指针开销;unordered_map 用哈希表,平均 O(1),但元素无序,结果依赖哈希函数质量,最坏情况(大量冲突)会退化,还可能因为扩容触发整表 rehash 导致迭代器失效。选型看需求:需要有序遍历、范围查询、或者对最坏延迟敏感(实时性场景)就选 map;只做高频单点查且 key 分布良好就用 unordered_map。

中断上下文为什么什么都不能做:中断由硬件触发,CPU 保存现场后跳进中断服务函数执行,处理完再回到原处继续。它没有可调度的进程上下文,所以绝对不能阻塞、休眠或等待信号量;也不能调用 printf 这类内部带锁的函数,因为锁一旦被别的任务持有就会死等,而且中断里做耗时操作会直接推高系统延迟、丢掉后续中断甚至触发看门狗。正确的做法是中断里只做最短的必要事——读走数据、清标志、置一个任务通知或往队列里投递,把协议解析、打印、业务处理交回任务。

C 与 C++ 的差别,以及这场面试的考察结构:C 面向过程,以函数和数据结构组织代码;C++ 在兼容 C 的基础上加了类、封装、继承、多态(虚函数表),还有模板、STL、引用、函数重载、异常这些特性,抽象能力和复用性更强,代价是有运行时开销和更复杂的对象模型。整场一面偏 C/C++ 基础加嵌入式基础,再往项目上深挖,没有偏题,重点是基础是否扎实、项目是不是真做过——面试官会顺着项目细节一层层追问,所以简历上写的每个模块都得能讲出实现和取舍。反问环节值得用来确认岗位形态:同样是「嵌入式」,做的可能是 MCU 上的固件,也可能是 Linux 侧的应用或驱动,技术栈和成长路径完全不同,问清楚比事后后悔划算。