第3章 字符设备驱动面试题:注册、打开、读写、ioctl、mmap实现细节
📌 面试问答卡片
卡片1 · 字符设备注册与 file_operations 初始化
面试问题:请描述字符设备驱动的注册流程,file_operations 结构体中哪些成员必须实现?
考察点:驱动基础框架理解、模块入口/出口规范、设备号管理。
回答框架:分配设备号 → cdev_init → cdev_add → 创建设备文件。必须实现:open/read/write/ioctl/release。
示例回答:“先用 alloc_chrdev_region 获取动态主次设备号,然后 cdev_init 绑定 file_operations,cdev_add 注册到系统,最后通过 class_create + device_create 自动创建设备节点。至少实现 open、release、read、write,若需控制则实现 unlocked_ioctl。”
可能追问:alloc_chrdev_region 与 register_chrdev_region 区别?卸载时 cdev_del 顺序?设备节点手动创建方法?
卡片2 · 读写与用户态数据拷贝
面试问题:驱动中的 read/write 如何安全地访问用户空间数据?为什么要用 copy_from_user 而非直接 memcpy?
考察点:地址空间隔离、睡眠安全、指针有效性检查。
回答框架:用户指针不可信 → copy_from/to_user 自动处理缺页并检查可访问性 → 若失败返回 -EFAULT。
示例回答:“用户传入的 buf 是用户虚拟地址,内核不能直接访问,需用 copy_from_user 到内核缓冲区操作,函数内部会检查地址范围、处理缺页,返回未拷贝字节数,非零则返回 -EFAULT。如果确定当前上下文可睡眠(非中断),也可以使用其变种 __copy_from_user。”
可能追问:spinlock 保护下能否使用 copy_from_user?get_user/put_user 与 copy_* 差异?zero-copy 方法有哪些?
卡片3 · ioctl 与 mmap 实现细节
面试问题:ioctl 如何设计命令编号?mmap 在内核中如何实现物理内存映射?请简述关键步骤。
考察点:驱动控制接口设计、命令编码规范、内存映射原理、vma 操作。
回答框架:ioctl:使用 _IO/_IOR/_IOW/_IOWR 宏生成唯一命令 → switch-case 处理。mmap:do_mmap → 设置 vma->vm_ops → fops->mmap 中调用 remap_pfn_range。
示例回答:“ioctl 命令使用类型、编号、大小、方向四要素编码,例如 #define MY_IOCTL_SET _IOW('M', 1, int)。mmap 实现:驱动分配物理连续内存或 dma_alloc_coherent,file_operations->mmap 中调用 remap_pfn_range(vma, vma->vm_start, virt_to_phys(addr)>>PAGE_SHIFT, size, vma->vm_page_prot)。”
可能追问:unlocked_ioctl 与 ioctl 区别?如何保证 mmap 与 read 的数据一致性?vm_area_struct 中 vm_ops 的 open/close 何时调用?
🧩 项目案例模板:智能传感器数据采集驱动
| 维度 | 内容 |
|---|---|
| 项目名称 | 多通道温度/湿度传感器字符驱动(i.MX6ULL + Linux 4.19) |
| 业务背景 | 工业环境监测设备需通过 SPI 总线读取 8 路传感器,用户应用程序需高效获取实时数据并支持配置采样率。 |
| 规模指标 | SPI 速率 10MHz,每通道采样频率 100Hz,驱动缓冲区 ring buffer 大小 4KB,支持 4 个并发打开。 |
| 技术栈 | Linux 字符驱动框架、SPI 子系统、自旋锁 + 原子变量、copy_from_user、unlocked_ioctl、remap_pfn_range。 |
| 核心难点 | ① SPI 操作在中断上下文与用户 read 的同步;② mmap 映射 dma_alloc_coherent 内存的缓存一致性;③ ioctl 命令扩展性设计。 |
| 面试高频追问 | ① 为什么用自旋锁而非信号量?② mmap 后如何保证用户看到最新数据?③ ioctl 命令编号如何防止冲突? |
| 可迁移回答话术 | “SPI 中断中不能睡眠,用 spin_lock 保护共享缓冲区;mmap 使用 dma_alloc_coherent 保证一致性;ioctl 命令采用 _IOW 宏绑定设备类型,上层通过统一定义头文件避免冲突。” |