面灵AI→

海康慧影 BSP 方向软件开发面经

时间
2026-10
来源
牛客网

《面试题目》

  1. 自我介绍
  2. 介绍一下项目
  3. 项目中遇到的难题是什么,怎么解决的?
  4. 用过 Linux 吗?
  5. uboot 的启动流程是怎样的?
  6. 二值信号量和计数信号量有什么区别?
  7. 信号量和互斥锁有什么区别?
  8. 什么场景下使用信号量、什么场景下使用互斥锁?
  9. 32 位系统和 64 位系统有什么区别?
  10. long 整型在 32 位和 64 位系统中分别是多大?
  11. 你对结构体对齐的理解是怎样的?
  12. 串口接收数据后,处理数据该怎么设计(RTOS 场景)?

《参考解析》

uboot 启动流程:典型的两阶段结构。第一阶段(汇编为主)做 CPU 最基础的初始化:设置异常向量表、关中断、配置时钟与 PLL、初始化内存控制器和串口(为了能打印),然后为第二阶段准备 RAM 空间并把自身代码搬过去,最后跳到 C 入口。第二阶段用 C 完成板级初始化:串口、定时器、MMU/cache、环境变量读取、设备树解析、网卡与存储驱动,之后进入命令行或按 bootcmd 自动启动内核——把内核镜像与设备树、根文件系统地址准备好,设置 bootargs(console、root、rootfstype 等),最后跳转到内核入口。面试常追问的几点:为什么要分两阶段(前段空间受限、不能用复杂 C)、重定位是干什么的、镜像校验(签名、CRC)放在哪一步、以及 bootargs 里参数如何传到内核。

信号量与互斥锁:二值信号量取值只有 0/1,通常用于「事件通知」或简单互斥;计数信号量初值为 N,用于管理 N 个同类资源(如缓冲区槽位、DMA 通道)。互斥锁的核心是所有权:只有加锁的任务能解锁,因此天然支持优先级继承——高优先级任务等锁时,持锁的低优先级任务临时提权,避免优先级反转;信号量没有所有者概念,不能做优先级继承,用在互斥场景就可能反转甚至死锁。所以「保护共享资源」用互斥锁,ISR 与任务之间或任务与任务之间的同步通知用信号量;中断里只能给信号量、不能拿互斥锁。实际项目里还要注意:不要在持锁期间做阻塞操作或调用可能阻塞的接口,临界区越短越好;RTOS 里给互斥锁设置优先级继承上限,并排查递归加锁。

32 位与 64 位、long 与结构体对齐:位宽差异体现在指针和 long 的宽度、地址空间上限、寄存器与调用约定上。以 LP64(Linux 64 位)为例,char 1、short 2、int 4、long 8、指针 8;而 Windows 的 LLP64 里 long 仍是 4 字节——所以跨平台代码里表示长度用 size_t、表示固定宽度用 stdint.h 的 int32_t/int64_t,别用 long。结构体对齐的规则是:每个成员相对结构体起始的偏移必须是自身对齐值的整数倍,结构体总大小要补齐到最大成员对齐值的整数倍;对齐值一般是成员大小与编译器对齐上限的较小者,可用 #pragma pack 或 __attribute__((packed)) 调整。实践中的坑:协议报文、Flash 存储、共享内存里的结构体一旦跨编译选项或跨平台,布局可能不同,必须显式打包并做静态断言(_Static_assert(sizeof(T) == N));调整成员顺序(按大小降序排列)能减少填充、省内存。

串口收包后的数据处理设计:不要在高优先级中断里做解析。推荐分层:ISR 只做最少的事——读寄存器拿到字节、塞进环形缓冲区(或写入 RTOS 流缓冲区),必要时给信号量/发任务通知,然后立刻退出;解析放到独立任务里,从缓冲区取数据、按协议做状态机解析(找帧头、校验长度与 CRC),解析成完整帧后通过消息队列投递给业务任务。这样做的理由是中断里不能阻塞、不能用互斥锁、不能做耗时运算,缓冲区要处理溢出(丢最旧还是丢最新要有明确策略并计数)。工程细节还包括:DMA + 空闲中断接收不定长数据、用双缓冲减少拷贝、给环形缓冲区做无锁设计(单生产者单消费者时读写指针各自独占即可)、给解析任务设置合理的优先级与栈水位、对丢包与错误帧打统计便于定位。

项目拷打与「难题」怎么答:这类问题考察的是你真做过什么。准备时每个项目挑一到两个能讲透的点,按「背景 → 现象 → 定位过程 → 根因 → 修复与验证 → 沉淀」讲:定位过程要有具体手段(日志分级打点、dmesg、示波器/逻辑分析仪看时序、二分法注释代码、加计数器统计异常路径),根因要落到机制层面而不是「改了个参数就好了」,验证要说清怎么复现和怎么确认不再出现。另外把项目里的量化信息准备好:代码量、负责模块、板子型号与来源、团队规模与你的角色边界,这些是 BSP 岗最容易被追问的细节——答不上来会让面试官怀疑项目参与深度。