3. 面试评分表与模拟面试清单
本章定位:字符设备驱动是Linux驱动面试中出场率最高的题型,围绕
file_operations、设备号分配、cdev注册与注销、用户态与内核态数据拷贝展开。面试官常通过“写一个简单的字符设备驱动”或“open/read/write流程”来考察基础功底。
问答卡片 1:写出字符设备驱动的注册与注销流程
| 面试问题 | 请描述注册一个字符设备驱动时需要做哪几步?如何注销? |
|---|---|
| 考察点 | 是否掌握 cdev 初始化、设备号申请、cdev_add、class_create 等接口;是否了解逆序注销。 |
| 回答框架 | (1)申请设备号(静态 MKDEV 或动态 alloc_chrdev_region)→(2)cdev_init 绑定 file_operations →(3)cdev_add 注册 →(4)创建 device class 和 device(自动生成设备节点)→ 注销步骤完全逆序:device_destroy → class_destroy → cdev_del → unregister_chrdev_region。 |
| 示例回答 | “先 alloc_chrdev_region 分配主次设备号,再 cdev_init 初始化 cdev 并关联 fops,接着 cdev_add 添加进内核;通过 class_create 创建类,device_create 创建设备节点。卸载时依次 device_destroy、class_destroy、cdev_del 和 unregister_chrdev_region。” (98字) |
| 可能追问 | ① 为什么建议用动态分配设备号?② cdev_add 之后设备就可用了吗?udev 的机制是什么?③ 注册和注销的加锁考虑。 |
| 避坑提醒 | 不要遗漏 class_create/device_create 后的错误处理(goto 释放已申请资源);注销顺序不可反,否则可能导致设备节点残留。 |
问答卡片 2:file_operations 中 open 与 release 的典型实现
| 面试问题 | 在字符设备驱动中,open 和 release 函数通常做什么?如何通过 private_data 传递设备结构体? |
|---|---|
| 考察点 | 对 inode 与 file 结构体的理解;container_of 宏的使用;驱动资源管理习惯。 |
| 回答框架 | (1)open 中通过 container_of(inode->i_cdev, struct my_dev, cdev) 获取设备结构体指针,赋值给 filp->private_data;(2)release 中从 filp->private_data 取出,做计数器递减或内存释放;(3)若使用引用计数,可在 release 中判断可卸载时机。 |
| 示例回答 | “open 里通过 container_of 拿到设备结构体,存到 file->private_data 供后续读写使用。release 取出后释放临时资源、减少引用计数。如果引用计数归零可触发模块清理,避免卸载时仍有打开句柄。” (82字) |
| 可能追问 | ① 为什么不直接用 inode->i_private?② 多设备实例时 private_data 如何区分?③ release 与 close 的原子性问题。 |
| 避坑提醒 | open 中要作错误判断(如设备正在移除);release 不保证每次 close 都对应 open(dup 场景),计数逻辑要正确。 |
问答卡片 3:内核空间与用户空间数据拷贝 API
| 面试问题 | 驱动中的 read/write 接口如何安全拷贝数据?为什么不能直接解引用用户态指针? |
|---|---|
| 考察点 | 是否了解 copy_to_user / copy_from_user;理解用户态内存的可换出性与访问权限;使用 access_ok 的前提。 |
| 回答框架 | (1)直接解引用会导致内核崩溃或安全漏洞,因为用户指针可能是无效、未映射或可换出的;(2)应使用 copy_from_user / copy_to_user,内部自动处理缺页和权限检查;(3)通常在开头用 access_ok 快速验证地址范围(可选,现代内核自动检查)。 |
| 示例回答 | “用户态指针不可直接在内核中访问,使用 copy_from_user 从用户空间拷贝到内核缓冲,copy_to_user 反向拷贝。这两个函数会在缺页时睡眠调度,且内嵌了地址合法性检查。调用前可加 access_ok 预检,但非必须。” (88字) |
| 可能追问 | ① 如果用户进程在拷贝期间被杀死会怎样?② __copy_from_user 与 copy_from_user 的区别?③ 为什么有些驱动用 get_user/put_user? |
| 避坑提醒 | 不要忘记对要拷贝的长度做合理校验(防止 buffer overflow);copy_to_user 的返回值要处理剩余未拷贝字节。切勿在自旋锁内使用拷贝函数(可能导致 sleep)。 |
公司侧重点分析
- 华为 / 海思:尤其看重驱动注册流程的安全性与错误回滚,面试常让你手写完整注册—注销代码,并要求考虑内存泄露和竞态。
高通 / 联发科:聚焦性能和 Low Latency,常追问 open 中的引用计数设计,以及如何避免用户态频繁开关设备。 - 小米 / OPPO:倾向结合具体场景(如 sensor 驱动、display 驱动),考察 file_operations 中 ioctl 的设计,以及多进程并发时如何保护 private_data。
- 字节跳动 / 蚂蚁:关注底层与安全,常让你对比 copy_from_user 与直接解引用的风险,并追问 access_ok 在新内核中是否已废弃。
面试官画像说明
字符设备驱动面试官通常为 BSP 团队资深工程师或技术主管(8~12 年经验)。他们打分核心依据:
• 基本功:能否流利背出注册注销接口顺序及参数(40%权重)
• 安全与健壮:是否主动提及错误处理 goto 机制、锁与拷贝的 sleep 限制(30%)
• 扩展思维:能否从单一驱动延伸到设备模型、设备树、ioctl 设计(30%)
典型提问风格:先让你写核心步骤,然后追问一个边缘 Case(如 “如果在 cdev_add 之后、device_create 之前系统崩溃怎么办?”),用以测试真实场景经验。
字符设备驱动面试官通常为 BSP 团队资深工程师或技术主管(8~12 年经验)。他们打分核心依据:
• 基本功:能否流利背出注册注销接口顺序及参数(40%权重)
• 安全与健壮:是否主动提及错误处理 goto 机制、锁与拷贝的 sleep 限制(30%)
• 扩展思维:能否从单一驱动延伸到设备模型、设备树、ioctl 设计(30%)
典型提问风格:先让你写核心步骤,然后追问一个边缘 Case(如 “如果在 cdev_add 之后、device_create 之前系统崩溃怎么办?”),用以测试真实场景经验。
面试禁忌:不要跳过错误处理;不要说“只需要一个 register_chrdev 就够了”;不要混淆 major 和 minor 位的计算方式;不要忽略 udev/mdev 自动节点生成的依赖关系。