第2章 内核模块、驱动框架、文件操作接口面试要点
本章聚焦驱动开发三大基础考点:内核模块生命周期、字符设备驱动框架、文件操作接口实现。大厂面试统计显示,80% 的驱动岗位初面围绕这三个方向展开,是必须牢固掌握的基石内容。以下先给出驱动框架的结构化回答路径,再逐一拆解核心问答。
本章速览:三大考点——① 内核模块加载/卸载与宏原理;② 字符设备驱动注册与 file_operations 实现;③ 并发控制机制选择。每个考点配套「追问路径」与「避坑提醒」,末尾附真实项目案例。
📌 面试问答卡 1:内核模块加载与卸载
💬 面试问题
请简述 Linux 内核模块的加载与卸载流程,说明 module_init 和 module_exit 宏的作用原理。
🎯 面试官考察点
- 是否理解内核模块的编译与运行时机制
- 是否清楚
__init/__exit段属性与内存释放 - 对模块依赖、版本校验、许可证声明的认知
🧩 回答框架
- 宏本质:
module_init将函数指针放入.initcall段,module_exit放入.exitcall段 - 加载流程:
insmod→ 内核遍历.initcall执行入口函数 → 完成初始化 - 卸载流程:
rmmod→ 内核遍历.exitcall执行清理函数 → 释放资源 - 必备声明:
MODULE_LICENSE("GPL")、MODULE_AUTHOR等
📝 简短示例回答
module_init 将初始化函数指针放入 .initcall 段,insmod 时内核遍历该段执行入口函数完成初始化。module_exit 类似,rmmod 时执行清理。模块需用 MODULE_LICENSE("GPL") 声明协议,否则内核标记为"污染"。
🔍 可能追问
initcall优先级机制(pure_initcall→fs_initcall等)module_init与late_initcall的区别- 模块参数如何传递(
module_param)
⚠️ 避坑提醒:忘记声明
MODULE_LICENSE 导致加载警告;混淆 module_init 与 __init 属性;在 module_exit 中未完整释放资源(cdev_del、unregister_chrdev_region)造成泄漏。
📌 面试问答卡 2:字符设备驱动框架与 file_operations
💬 面试问题
请描述字符设备驱动的核心框架,file_operations 结构体中哪些接口最常用?实现时有哪些关键注意事项?
🎯 面试官考察点
- 是否掌握字符设备驱动注册三步流程
- 对用户态 ⇄ 内核态数据拷贝的理解深度
- 是否具备设备号管理与错误处理的工程意识
🧩 回答框架
- 注册流程:
alloc_chrdev_region→cdev_init→cdev_add - 常用接口:
open/release/read/write/unlocked_ioctl - 数据拷贝:必须使用
copy_from_user/copy_to_user,禁止直接解引用用户指针 - 错误处理:每个步骤检查返回值,失败时回滚已分配资源
📝 简短示例回答
字符设备驱动核心是
file_operations 结构体。注册三步:alloc_chrdev_region 分配