当前位置:首页>Linux>27届秋招嵌入式驱动岗,这10个Linux问题,面试官能追到probe

27届秋招嵌入式驱动岗,这10个Linux问题,面试官能追到probe

  • 2026-10-10 22:21:53
27届秋招嵌入式驱动岗,这10个Linux问题,面试官能追到probe

点击上方“嵌入式Linux充电站”,选择“置顶/星标公众号”

福利干货,第一时间送达

最近看了一些 27 届同学的准备情况,发现一个很典型的问题:

很多人不是完全不会 Linux 驱动,而是只会背一层。

面试官问:

probe 为什么没有执行?

你答:

compatible 没匹配上。

这个答案不能说错,但大概率接下来就会被继续追问:

那除了 compatible,还有哪些原因? 如果 compatible 是对的,你怎么定位? deferred probe 见过吗? 驱动编进内核和 ko 加载有什么区别?

这时候很多人就开始卡壳了。

嵌入式驱动岗的面试,最怕的不是你不知道某个 API,而是你没有把“设备树、驱动模型、中断、内存、并发、调试”串起来。

下面这 10 个问题,是我觉得 27 届秋招准备 Linux 驱动岗必须吃透的。不是让你背答案,而是要能经得住追问。


1. 驱动的 probe 为什么没有执行?

很多同学第一反应就是:

设备树 compatible 没匹配上。

这只答到了一点。

真正面试的时候,你至少要能从这几个方向排查:

  1. 驱动有没有被编译进去看 Kconfig、Makefile、.config,确认是 built-in 还是 module。

  2. module 有没有加载成功如果是 ko,看 lsmod、insmod/modprobe 返回值,以及 dmesg。

  3. 设备树节点有没有生效看节点路径、status = "okay"、compatible 字符串、父节点状态。

  4. bus match 规则是否匹配platform 驱动一般看 of_match_table,I2C/SPI 还要看设备有没有被对应 bus 创建出来。

  5. 依赖资源是否没准备好比如 clock、regulator、gpio、pinctrl、reset 控制器没有就绪,可能触发 -EPROBE_DEFER。

  6. probe 执行了但失败返回有些人只看“有没有打印”,但 probe 可能进去了,只是在中间申请资源失败后返回了。

比较好的回答方式是:

我会先确认驱动是否加载,再确认设备是否创建,接着看 bus 的 match 过程,最后检查 probe 内部资源申请是否失败。如果是设备树驱动,会重点看 compatible、status、节点路径和依赖资源。实际排查时主要看 dmesg、/sys/bus/platform/devices、/sys/bus/platform/drivers 以及动态调试信息。

面试官听到这个答案,基本会知道你不是只会背 compatible。


2. platform_driver 和 platform_device 是怎么匹配的?

你不能只说:

通过 name 或 compatible 匹配。

要把优先级讲清楚。

一般来说,设备树场景下重点看 of_match_table,也就是驱动里的:

staticconststructof_device_idxxx_of_match[] = {    { .compatible = "vendor,xxx-device" },    { }};MODULE_DEVICE_TABLE(of, xxx_of_match);

设备树节点里会写:

xxx@12340000 {    compatible = "vendor,xxx-device";    reg = <0x12340000 0x1000>;    status = "okay";};

内核启动解析设备树后,会把节点转换成 platform device。驱动注册后,platform bus 会尝试匹配 device 和 driver。匹配成功后,才会调用 probe。

面试官继续追问时,常见方向有三个:

  1. 如果没有设备树,怎么创建 platform_device?
  2. name 匹配和 of_match_table 匹配有什么区别?
  3. 为什么有的驱动明明注册了,/sys 下却没有对应设备?

你要能说出一点:驱动注册不等于设备存在。driver 和 device 是两边,只有两边都准备好,才谈得上 match 和 probe。


3. 中断里为什么不能睡眠?

这个问题看起来简单,但很容易暴露基础。

中断上下文里不能睡眠,核心原因是:

中断上下文没有普通进程上下文,不能像进程一样被调度器安全地挂起和恢复。

所以在中断处理函数里,不能做可能睡眠的操作,比如:

  • mutex_lock()
  • msleep()
  • 可能阻塞的内存申请
  • 可能等待用户态或设备慢操作的逻辑

那中断来了之后事情又很多怎么办?

通常要拆成上半部和下半部。

上半部做最少的事情:

  • 读取中断状态
  • 清中断
  • 保存必要信息
  • 唤醒后续处理

下半部再做耗时逻辑:

  • tasklet
  • workqueue
  • threaded irq

现在面试更喜欢追问 threaded irq。

如果你能说出:

hard irq 里做快速响应,threaded irq 里可以跑在内核线程上下文,能做相对复杂的处理,也能使用可能睡眠的接口。

这个回答就比只背“中断不能睡眠”强很多。


4. spinlock 和 mutex 怎么选?

最核心的区别:

spinlock 忙等,不能睡眠;mutex 可能睡眠。

所以选择时先看上下文:

  1. 中断上下文用 spinlock,不能用 mutex。

  2. 进程上下文,临界区可能睡眠用 mutex。

  3. 临界区很短,且可能被中断访问用 spinlock,并考虑 spin_lock_irqsave()。

  4. 只保护一个简单计数可以考虑 atomic 或 refcount,不一定要上锁。

常见追问是:

为什么持有 spinlock 时不能调用 copy_to_user?

因为 copy_to_user() 访问用户空间地址,可能触发缺页异常,可能睡眠。持有 spinlock 时睡眠,会导致严重问题。

你可以这样答:

我会先判断代码运行在哪种上下文,再判断临界区是否可能睡眠。如果可能在中断里访问,不能用 mutex。如果只是进程上下文并且临界区里会调用可能睡眠的 API,就应该用 mutex。

锁这个问题,不是背 API,而是判断上下文。


5. copy_to_user 和 copy_from_user 为什么不能随便用?

字符设备驱动里,read()、write()、ioctl() 很容易遇到这两个函数。

copy_from_user() 是从用户空间拷贝数据到内核空间。copy_to_user() 是从内核空间拷贝数据到用户空间。

它们不能直接用 memcpy() 替代,因为用户态地址不可信:

  • 地址可能非法
  • 页可能不在内存中
  • 访问可能失败
  • 用户态可能传一个恶意地址

所以内核要通过专门接口访问用户空间。

面试官经常继续问:

copy_to_user 返回值是什么?

它返回的是没有成功拷贝的字节数,不是成功返回 0、失败返回负数这种普通风格。

所以常见写法是:

if (copy_to_user(buf, kbuf, len))return -EFAULT;

还会追问:

ioctl 里传结构体指针怎么处理?

基本思路是:

  1. 定义内核结构体变量
  2. 用 copy_from_user() 拷进来
  3. 检查参数合法性
  4. 操作硬件或内核状态
  5. 必要时再 copy_to_user() 回去

这类问题考的是你有没有真正写过用户态和内核态交互。


6. 阻塞 IO、非阻塞 IO、poll/epoll 是怎么配合驱动的?

很多驱动不是用户一读就有数据。

比如按键、触摸、传感器、中断事件,都可能需要等。

如果没有数据,驱动有两种处理方式:

  1. 阻塞模式进程睡眠,等事件来了再唤醒。

  2. 非阻塞模式立即返回 -EAGAIN,让用户态自己决定后续怎么处理。

驱动里通常会用等待队列:

wait_event_interruptible(wq, condition);

事件来了,比如中断里或 workqueue 里:

wake_up_interruptible(&wq);

如果用户态用 poll() 或 epoll(),驱动要实现 .poll:

static__poll_txxx_poll(struct file *file, poll_table *wait){    poll_wait(file, &wq, wait);if (data_ready)return POLLIN | POLLRDNORM;return0;}

面试里你要能说清楚:

poll 不是自己睡眠等数据,而是把当前等待队列注册进去。真正有事件时,驱动唤醒等待队列,用户态 poll/epoll 才会返回。

这个点很多人会混。


7. ioremap 是干什么的?为什么不能直接访问物理地址?

设备树里 reg 描述的是物理地址范围,但内核代码不能直接拿物理地址当指针用。

原因很简单:

CPU 运行在虚拟地址环境下,驱动需要把设备物理地址映射成内核虚拟地址。

所以会用:

base = devm_ioremap_resource(dev, res);

或者老一点的写法:

base = ioremap(phys, size);

之后访问寄存器,应该用:

readl(base + offset);writel(val, base + offset);

而不是直接:

*(volatileunsignedint *)(base + offset) = val;

面试官可能会追问:

为什么要用 readl/writel?

因为 MMIO 访问不是普通内存访问,涉及访问顺序、屏障、架构差异等问题。内核提供 readl/writel 就是为了让驱动以架构无关的方式访问设备寄存器。

这个问题也是区分“写过裸机”和“理解 Linux 驱动”的地方。


8. DMA 一致性问题怎么理解?

最容易被问的是:

CPU 和 DMA 同时访问一块内存,会有什么问题?

核心问题是 cache。

CPU 访问内存时可能走 cache,设备 DMA 访问内存时通常直接访问内存。如果 CPU cache 里的数据和内存里的数据不一致,就会出问题。

典型问题:

  1. CPU 写了数据,但还在 cache 里,DMA 读不到最新内容。
  2. DMA 写了数据到内存,但 CPU 读到的是旧 cache。

常见 DMA 内存有两类:

  1. coherent DMA用 dma_alloc_coherent() 申请,CPU 和设备看到的数据保持一致,使用简单,但不一定适合所有场景。

  2. streaming DMA用 dma_map_single()、dma_unmap_single() 等接口,需要在 DMA 前后做同步,适合一次性或阶段性传输。

回答时不要只说“刷 cache”。

更好的说法是:

DMA 一致性的本质是 CPU cache 和设备访问内存之间的一致性问题。Linux 驱动里不应该自己随便操作 cache,而应该使用 DMA API,让内核根据架构处理映射、同步和 cache 维护。

这句话很重要。


9. 设备树里的 pinctrl、clock、reset、regulator 分别解决什么问题?

面试官问设备树,不一定是问 compatible。

他更想知道你是否理解这些资源:

  1. pinctrl配引脚复用和电气属性。比如这个 pin 到底是 GPIO、UART、I2C 还是 SPI。

  2. clock外设模块需要时钟,不开时钟寄存器可能读写没反应。

  3. reset有些 IP 上电后需要释放 reset,否则模块一直不工作。

  4. regulator管电源。传感器、屏幕、WiFi、音频 codec 都可能依赖电源轨。

  5. interrupts描述中断号和触发方式。

  6. reg描述寄存器物理地址和长度。

所以一个外设驱动 probe 里经常会做:

  • 获取寄存器资源
  • ioremap
  • 获取 clock 并 enable
  • 获取 reset 并 deassert
  • 获取 regulator 并 enable
  • 配 pinctrl 状态
  • 申请 irq

如果你能按这个顺序讲出来,面试官会默认你至少调过板子。


10. 驱动出问题,你怎么定位?

不要回答:

打印日志。

太浅了。

你可以按层次回答。

第一层,看启动和加载:

  • dmesg
  • probe 打印
  • 错误返回值
  • initcall 顺序
  • ko 加载日志

第二层,看 sysfs:

  • /sys/bus/platform/devices
  • /sys/bus/platform/drivers
  • /sys/class
  • /sys/kernel/debug

第三层,看中断:

  • /proc/interrupts
  • 中断计数有没有增加
  • 触发方式是否正确
  • 中断是否被 mask

第四层,看设备树:

  • /proc/device-tree
  • compatible 是否一致
  • status 是否 okay
  • reg/interrupts/pinctrl/clock 是否配置完整

第五层,看动态调试:

  • dynamic_debug
  • ftrace
  • tracepoint
  • function graph

如果是用户态调用驱动异常,还可以看:

  • strace
  • 返回 errno
  • read/write/ioctl 参数

一个比较完整的回答是:

我会先判断问题发生在驱动没有加载、probe 没进、probe 失败、设备节点没生成、用户态访问失败,还是硬件没有响应。不同阶段用不同工具,而不是一上来就盲目加 printk。

这就是项目经验和背八股的区别。


最后说一下:这 10 个问题怎么复习?

建议按这条线串起来:

  1. 设备树怎么描述硬件
  2. platform device 怎么创建
  3. platform driver 怎么注册
  4. device 和 driver 怎么匹配
  5. probe 里怎么拿资源
  6. 怎么访问寄存器
  7. 怎么处理中断
  8. 怎么处理并发
  9. 怎么和用户态交互
  10. 出问题怎么定位

这条线走通了,Linux 驱动面试的大部分问题都能接住。

很多同学准备秋招时,会把时间花在背 API 名字上。但面试官真正想看的,是你能不能把一个外设从设备树、probe、寄存器、中断、用户态接口到问题定位完整讲下来。

如果你现在只能零散回答,那就别急着刷更多题。

先把这 10 个问题吃透。

能经得住追问,才算真的会。

ending

一个人可以走得很快,一群人才能走得更远。我创建了
知识星球,如果你也需要一个良好的学习环境,加入星球,跟我一起进步。这是一个笔试刷题+面试取经+就业指导+经验分享的私密圈子,你可以阅读星球专栏、向我提问,一起进步成长。
当前星球内容有:
1、八股文,部门内容预览:
网络:
算法:
驱动/操作系统相关:
2、大厂校招笔试真题集:
(当前已涵盖大疆、小米、联发科、VIVO、字节、影石、德赛西威、海康威视、理想、蔚来、经纬恒润、美团、芯原股份、全志科技、诺瓦星云、CVTE、科大讯飞、芯动科技)
3、大厂校招面经合集:
部分内容预览:
加入我们,一起见证飞一样的成长:

end

往期推荐

直到我干了底层开发,才知道不写业务代码有多爽

你解决bug的能力,暴露了你的水平

入职Linux驱动工程师后,我才知道的真相......

很底层的性能优化:让CPU更快地执行你的代码

薪资倒挂,大家都沉默了...

机遇:我是如何走向Linux驱动的...

当我用几道题考了一遍做Linux驱动的同事..

最新文章

随机文章