3. 字符设备驱动开发面试要点

字符设备驱动是 Linux 驱动开发面试的必考模块,占据基础题 70% 以上。本节聚焦四个核心考点:设备号分配、file_operations 结构体、cdev 注册流程、并发控制。面试官常要求口述完整注册流程,并追问竞态场景。

考点权重:设备号分配 (20%) + file_operations (30%) + cdev 注册 (30%) + 并发控制 (20%)
字符设备驱动注册全流程 → 面试回答框架 1. 分配设备号 2. 初始化cdev 3. 设置ops 4. 添加cdev 5. 创建设备节点 加分细节 • alloc_chrdev_region vs MKDEV • 设备号范围:MAJOR & MINOR 易错点 • cdev_init后必须设置owner • 忘记class_create自动创建设备节点
面试话术结构:先概括流程链路,再逐层展开关键函数调用,最后抛出并发控制方案。例如:“我会先调用 alloc_chrdev_region 动态分配设备号,然后 cdev_init 关联 file_operations,最后通过 cdev_add 注册到内核,并利用 udev 自动创建设备节点。”

常规问答卡片

Q1:字符设备驱动中如何分配设备号?动态分配和静态分配的适用场景?

考察点:是否理解主次设备号、接口函数区别、实际项目选择倾向。

回答框架:先给出两种方式 API → 说明区别 → 结合实际场景建议。

示例回答:动态分配用 alloc_chrdev_region(&dev, 0, 1, "mydrv"),内核自动分配主设备号;静态分配用 register_chrdev_region(dev, 1, "mydrv") 需已知编号。项目初期推荐动态分配避免冲突,产品定型后也可固定主设备号。

可能追问:主设备号和次设备号各多少位?cat /proc/devices 能查到什么?

避坑:一定检查 alloc_chrdev_region 返回值,使用 IS_ERR() 处理失败情况;卸载时调用 unregister_chrdev_region 释放。

Q2:请列举 file_operations 中至少 5 个常用回调函数,并说明其调用时机和典型实现。

考察点:对驱动与 VFS 交互模型的理解深度;是否区分阻塞与非阻塞。

回答框架:分层列举 open/release → read/write → unlocked_ioctl/llseek → mmap 等。

示例回答:open 初始化私有数据;release 释放资源;read 将内核数据拷贝到用户空间(copy_to_user);write 从用户空间接收数据(copy_from_user);unlocked_ioctl 处理自定义命令;llseek 更改文件偏移。

可能追问:为什么现在推荐 unlocked_ioctl 而不是 ioctl?.owner 成员为何要设为 THIS_MODULE?

避坑:read/write 必须检查用户空间指针合法性(access_ok),并处理信号中断返回 -ERESTARTSYS;.owner 不设置会导致模块卸载时崩溃。

Q3:cdev 注册的完整步骤是怎样的?当多个进程同时 write 时会遇到什么问题?如何解决?

考察点:是否掌握 cdev_init + cdev_add 链路;并发控制方案选择。

回答框架:注册步骤三步 → 竞态问题描述 → 保护方案(自旋锁/互斥体/原子操作)。

示例回答:步骤:cdev_init → cdev.owner = THIS_MODULE → cdev_add。多进程并发 write 可能导致数据错乱,使用 mutex_lock 保护临界区:在 write 开头加锁、末尾解锁,确保一次只有一个进程写入。

可能追问:spin_lock 和 mutex 如何选择?中断上下文能否用 mutex?

避坑:cdev_add 之后设备立即可访问,必须在 cdev_add 之前完成所有初始化;并发控制粒度不宜过大(锁整个驱动),应按资源加锁。

项目案例章节

STAR 项目表达框架 — 多通道数据采集驱动 S 情境 8路ADC + FPGA 200K采样/秒 T 任务 驱动数据无丢失 多进程安全访问 A 行动 mmap零拷贝 读-拷贝-更新(RCU) R 结果 丢包率<0.01% 通过企业验收 面试表达技巧 先一句话定义背景 → 然后说“我负责核心驱动模块” 遇到高并发时用了RCU保证读不会被写阻塞

项目名称:多通道高速数据采集字符驱动

业务背景工业检测设备,需要采集8路ADC数据并通过PCIe传输到用户态分析软件
规模指标采样率 200K/s × 8通道,每秒产生约 3.2MB 数据;用户态 4 个并发进程读取
技术栈Linux 5.10,字符驱动框架,mmap,RCU锁,wait_queue,FPGA DMA
核心难点① 高频写入不丢数据;② 多进程无锁读取;③ 中断顶半部与底半部数据同步
面试高频追问
• 为什么选择 RCU 而不是读写锁?RCU 在什么场景下效率更高?
• mmap 如何确保 DMA buffer 不跨页?
• 如果采样率提升到 1M/s,你的方案哪里会成为瓶颈?
可迁移回答话术
“在这个项目中,我主要负责字符驱动核心模块。数据从FPGA经DMA写入内核预分配缓冲区,驱动通过字符设备暴露mmap接口实现零拷贝。针对多进程读竞争,我设计了RCU保护采样数据指针更新,读端无锁化,写端在更新完指针后再老数据无引用时释放。最终在高负载下丢包率控制在0.01%以内。”
面试加分点:在项目案例中主动提及“中断上下文不能使用mutex”并给出替代方案(如 workqueue + spinlock),能让面试官认为你具备生产级驱动开发经验。

章节 3/30 · 字符设备驱动开发面试要点