百度底层软硬件
8.27 一面 1h多
先问实习内容和几个项目细节
1.谈谈你对设备驱动框架的理解
我认为设备驱动框架是操作系统制定的一套标准化分层开发架构,采用分层设计实现软硬件解耦。框架统一规定了设备注册、初始化、读写、中断等通用接口,开发者只需完成底层硬件适配即可。上层应用无需接触底层硬件细节,直接调用通用接口操控设备,极大提升代码可移植性与开发效率,也方便系统统一管理各类外设资源。
分层思想(重点)
- 上层:应用层只调用系统提供的标准读写、打开、关闭接口,完全不懂硬件寄存器、时序电路。
- 中层:驱动框架层操作系统内核提供统一骨架,定义固定函数接口、设备注册机制、中断管理、设备节点管理,规定驱动该怎么写、怎么挂载。
- 下层:硬件适配层开发者只需要按照框架规定,填充硬件寄存器配置、引脚初始化、时序读写、中断服务等底层硬件逻辑即可。
2.介绍计算机网络模型和各协议
一、两大模型
- OSI 七层模型(理论)应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
- TCP/IP 五层模型(实际在用)应用层,传输层,网络层,数据链路层,物理层
数据链路层:ARP 把IP 地址转换成对应的MAC 物理地址
网络层:IP 分配主机地址(
A 类私有10.0.0.0 ~ 10.255.255.255
B 类私有172.16.0.0 ~ 172.31.255.255
C 类私有(最常用)192.168.0.0 ~ 192.168.255.255)
传输层:TCP、UDP
应用层:HTTP/HTTPS 网页访问、FTP/SFTP 文件传输、DNS 域名解析、SSH 远程登录 Linux
3.有了解过用户态的驱动开发吗
用户态驱动就是把硬件操作逻辑放在应用层用户空间实现,不侵入内核,不用编写内核模块。
串口控制机械臂直接打开 /dev/ttyUSBx 读写数据,应用层收发指令,纯用户态
4.介绍dma
DMA 直接存储器访问
不经过 CPU,直接让外设和内存之间高速搬运数据,解放 CPU
DMA 是直接存储器访问,能够在外设与内存之间不经过 CPU直接完成数据搬运,大幅减轻主控压力,提升传输效率,在串口、ADC、屏幕等大批量数据传输场景经常使用。
DMA 和中断区别?
中断是少量数据、事件通知;DMA 是批量高速搬运数据。
5.有用gdb调试过什么具体问题吗
系统报错只能告诉我们程序崩溃了,但无法定位具体代码行、无法查看变量、无法看到函数调用栈。
而 GDB 可以查看崩溃现场、查看堆栈、追踪变量、断点调试,尤其能解决段错误、死循环、死锁、逻辑异常这类系统不会提示的问题。
程序卡死、死循环
6.有了解日志打印这块具体的实现过程吗
定义日志等级,自动获取代码位置信息、获取标准时间戳、实现可变参数格式化
统一日志格式拼接,指定输出目的地、做多线程安全处理、封装对外调用宏函数、底层最终调用
日志打印具体实现分为十步,首先定义日志等级做日志过滤,借助编译器内置宏自动获取代码文件、行号与函数信息;调用系统时间接口拼接时间戳;通过可变参数解析格式化内容,组合成标准日志格式;支持控制台和本地文件两种输出方式;加入互斥锁解决多线程日志乱序问题;再实现日志文件分割管理,最后封装成简易调用宏,底层依靠文件读写系统调用完成最终输出。
7.我的硬件调试经历,主要是哪个方向的
的硬件调试主要偏向嵌入式 Linux 机器人方向,擅长总线通信调试、机械臂运动硬件调试、视觉相机设备调试,以及上下位机整体软硬件联调,擅长用仪器排查时序、通信、硬件电路与数据交互类问题。
8.确认fpga的水平(后面看)
FPGA 是能反复改写硬件电路的高速可编程芯片,主打快、稳、实时强,多用于机器人、工控、AI 硬件本地化部署。
9.有了解过用户态程序中性能优化的手段吗,有了解过内存池吗
用户态 = 应用程序代码(C/C++/Go/Java 都算),不涉及内核。
1. 计算优化
- 减少循环嵌套、减少重复计算
- 用更高效的算法(O (n) → O (logn))
- 避免频繁的函数调用、虚函数开销
2. 内存优化(最重要)
- 减少内存拷贝(零拷贝)
- 避免频繁 malloc/free(用内存池)
- 提高缓存命中率(局部性原理)
- 对齐内存、减少内存碎片
3. I/O 优化
- 异步 I/O 代替阻塞 I/O
- 批量读写、减少系统调用
- 使用缓冲区、减少磁盘 / 网络访问次数
4. 并发 / 锁优化
- 减少锁范围、用无锁数据结构
- 用原子操作代替互斥锁
- 协程 / 线程池避免频繁创建销毁
5. 系统调用优化
- 减少
read/write/open等系统调用(非常耗性能) - 用户态批量处理,不要频繁进内核态
1.为什么要用内存池?
malloc/new是系统调用,频繁申请释放非常慢- 频繁申请会产生内存碎片
2. 内存池解决什么问题?
- 提速:避免频繁系统调用
- 减少碎片:连续内存,利用率更高
- 可控:自己管理,避免内存泄漏
- 稳定:高并发场景不抖动
(抖动 = 程序运行速度忽快忽慢、帧率不稳、响应时快时慢、卡顿波动)
10.c和c++区别
C 是面向过程的结构化语言,简洁轻量,多用于底层硬件开发;
C++ 在 C 基础上扩展面向对象特性,支持封装继承多态,开发大型复杂项目更合适,语法更丰富,工程化能力更强。
- 头文件
- C:
#include <stdio.h> - C++:
#include <iostream>,用std::cout打印
- C:
- 输入输出
- C:
printf / scanf - C++:
cout / cin
- C:
- 字符串
- C:
char[]字符数组 - C++:
string类,好用不用手动处理结束符
- C:
- 内存管理
- C:
malloc / free - C++:
new / delete,自动调用构造析构
- C:
- 函数
- C:不支持函数重载
- C++:支持函数重载、默认参数
- 结构体
- C:结构体不能放函数
- C++:结构体 = 类,可写成员函数
- 关键字
- C++ 独有:
class、public、private、protected、this、inline、template、namespace
- C++ 独有:
8. 编程思想最大差距
- C:怎么做(步骤)拆成一个个函数,按顺序执行
- C++:是谁做(对象)封装、继承、多态三大特性
11.介绍RAII
在构造函数里申请资源,在析构函数里自动释放资源,依靠对象生命周期自动管理资源,不用手动写释放代码。
RAII 是 C++ 独有的资源管理机制,利用类的构造函数获取资源、析构函数释放资源,依靠对象生命周期自动管理内存、锁、文件、网络等资源,无需手动释放,从语法层面杜绝资源泄漏。
12.智能指针(前面已介绍)
常见问题
- 野指针:智能指针生命周期结束自动置空,大幅减少野指针
- 内存泄漏:RAII 自动释放,基本杜绝
- 循环引用:两个 shared_ptr 互相持有 → 计数永远不为 0 → 泄漏,用 weak_ptr 打破
- 能不能混用裸指针和智能指针?不建议,容易二次释放崩溃
智能指针基于 C++ RAII 思想封装裸指针,实现堆内存自动管理;日常优先用unique_ptr,多线程多对象共享资源用shared_ptr,搭配weak_ptr解决循环引用问题。
13.用c语言能否实现面向对象
C 是面向过程语言,无class、无继承多态原生关键字,靠结构体 + 函数指针模拟 OOP 三大特性。
1.怎么模拟
-
封装,用
struct存成员属性,把操作该数据的函数指针放进结构体,外部只调用接口,隐藏内部实现。 -
继承,把子类结构体第一个成员放父类结构体,实现内存布局复用,达成继承效果。
-
多态,通过函数指针数组 / 重写函数指针,不同结构体绑定不同实现函数,调用同一接口执行不同逻辑,模拟虚函数多态。
14.如何用c语言实现RAII
C 语言没有原生构造析构,无法原生实现 RAII,只能手动模拟:
- 编写资源初始化函数模拟构造,完成内存、句柄、锁等资源申请;
- 编写统一资源释放函数模拟析构;
- 通过
goto设置统一释放入口,保证函数正常退出、异常返回时必然执行释放逻辑; - 借助代码作用域划分生命周期,复刻 C++ RAII
15.c可以调用c++吗,如何实现
C 可以调用 C++,但必须用 extern "C" 修饰 C++ 接口,禁止使用 C++ 特有的语法(类、重载、模板),对外暴露纯 C 风格函数;若涉及 C++ 对象,则用 void 指针隐藏对象实现,让 C 语言可以正常调用。
// 必须加 extern "C",让C能找到
#ifdef __cplusplus
extern "C" {
#endif
// 纯 C 风格接口
int add(int a, int b) {
return a + b;
}
#ifdef __cplusplus
}
#endif
#include <stdio.h>
// 声明 C++ 暴露的函数
int add(int a, int b);
int main() {
int res = add(10, 20);
printf("结果:%d\n", res);
return 0;
}
16.经典接雨水原题(看)
9.16 二面 1.5h
1.介绍实习内容中的整体方案,之后问了非常多问题,代码框架、必要性、细节实现、适用范围、对外接口、提交的代码量、具体遇到的技术难题
2.问完这段问下一段实习内容,每个点都会问的很细
3.继续问在校竞赛项目,确认团队人数继续问项目中的具体实现
4.分享其中一段有软硬结合协调的经历
5.介绍gdb使用经历,平时调试的主要手段有
6.了解设备树吗,有哪些技术点,如何实现这种驱动或设备注册加载的
设备树 (Device Tree):Linux 内核用来描述板级硬件资源的树形文本文件,后缀.dts、.dtsi。作用:把硬件信息从内核代码剥离,不用改内核源码、重新编译内核,只改设备树就能适配不同硬件。
以前:平台硬件差异全写在内核 C 代码里,换一块板子就要改代码、编译内核,臃肿难维护。
现在:硬件引脚、中断、时钟、寄存器地址、总线、电源全部写进设备树,内核统一解析匹配驱动
7.一道二叉树的题,最下层的两节点之间可能会出现空节点,计算二叉树的最大宽度(包含空节点)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)