第2章 内核模块、驱动框架、文件操作接口面试要点

本章聚焦驱动开发三大基础考点:内核模块生命周期、字符设备驱动框架、文件操作接口实现。大厂面试统计显示,80% 的驱动岗位初面围绕这三个方向展开,是必须牢固掌握的基石内容。以下先给出驱动框架的结构化回答路径,再逐一拆解核心问答。

字符设备驱动框架 · 结构化回答路径 应用层系统调用 open / read / write / ioctl VFS虚拟文件系统 sys_call 转发 / inode 查找 驱动注册 (cdev) alloc_chrdev_region / cdev_add 文件操作接口 copy_from_user / copy_to_user 硬件寄存器操作 ioremap / readl / writel / DMA
本章速览:三大考点——① 内核模块加载/卸载与宏原理;② 字符设备驱动注册与 file_operations 实现;③ 并发控制机制选择。每个考点配套「追问路径」与「避坑提醒」,末尾附真实项目案例。

📌 面试问答卡 1:内核模块加载与卸载

💬 面试问题

请简述 Linux 内核模块的加载与卸载流程,说明 module_init 和 module_exit 宏的作用原理。

🎯 面试官考察点

  • 是否理解内核模块的编译与运行时机制
  • 是否清楚 __init / __exit 段属性与内存释放
  • 对模块依赖、版本校验、许可证声明的认知

🧩 回答框架

  1. 宏本质:module_init 将函数指针放入 .initcall 段,module_exit 放入 .exitcall 段
  2. 加载流程:insmod → 内核遍历 .initcall 执行入口函数 → 完成初始化
  3. 卸载流程:rmmod → 内核遍历 .exitcall 执行清理函数 → 释放资源
  4. 必备声明: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 结构体中哪些接口最常用?实现时有哪些关键注意事项?

🎯 面试官考察点

  • 是否掌握字符设备驱动注册三步流程
  • 对用户态 ⇄ 内核态数据拷贝的理解深度
  • 是否具备设备号管理与错误处理的工程意识

🧩 回答框架

  1. 注册流程:alloc_chrdev_region → cdev_init → cdev_add
  2. 常用接口:open / release / read / write / unlocked_ioctl
  3. 数据拷贝:必须使用 copy_from_user / copy_to_user,禁止直接解引用用户指针
  4. 错误处理:每个步骤检查返回值,失败时回滚已分配资源

📝 简短示例回答

字符设备驱动核心是 file_operations 结构体。注册三步:alloc_chrdev_region 分配