C++ 怎么编写一个 Linux 字符设备驱动程序(Character Device Driver)实现用户态与内核态的高效交互

老涛吖_8615

老涛吖_8615

2026-11-03

838人浏览

原创

现代字符设备驱动应使用alloc_chrdev_region + cdev_init + cdev_add组合替代register_chrdev:前者支持动态分配设备号、精细管理次设备号并适配新内核机制,后者仅适用于主设备号

c++ 怎么编写一个 linux 字符设备驱动程序(character device driver)实现用户态与内核态的高效交互

字符设备驱动的核心注册流程(register_chrdev vs alloc_chrdev_region)

Linux 字符设备驱动不能靠简单调用 register_chrdev 就完事——它只适用于主设备号小于 256 的静态注册,且不支持设备号动态分配和更精细的 cdev 管理。现代驱动应优先用 alloc_chrdev_region + cdev_init + cdev_add 组合,否则在内核 5.10+ 上可能触发警告或无法创建设备节点。

实操要点:

  • alloc_chrdev_region 必须在 module_init 中尽早调用,失败时立即返回,避免后续内存泄漏
  • cdev_init 后必须显式设置 cdev.owner = THIS_MODULE,否则卸载模块时内核会 panic(常见于忘记这行)
  • cdev_add 的第三个参数是设备号数量(通常为 1),若传 0 会导致 -EINVAL 错误,dmesg 里看到 "cdev_add failed" 就先查这个

用户态读写如何触发内核回调(read/write 函数签名与原子性)

用户调用 read() 或 write() 时,内核最终执行你注册在 file_operations 结构体里的 read 和 write 成员函数。这两个函数签名和语义与 libc 不同:它们不保证一次完成全部 count 字节,必须返回实际处理字节数,且不能直接访问用户地址空间。

关键细节:

  • 必须用 copy_from_user(写入内核)和 copy_to_user(读出到用户)做地址空间转换,直接解引用 buf 指针会 oops
  • 函数返回值是“成功传输的字节数”,不是 0/1 成败标志;返回负值(如 -EFAULT)表示错误,会被用户态 read 返回 -1 并置 errno
  • 不要在 read/write 里睡眠(比如用 msleep),除非已将文件设为非阻塞且使用了等待队列——默认上下文是不可调度的原子上下文

设备节点怎么自动创建(class_create + device_create)

仅注册 cdev 不会生成 /dev/xxx 节点,用户态根本打不开。必须配合 class_create 和 device_create 让 udev 触发节点创建。跳过这步,mknod 手动建节点虽能用,但不符合现代驱动规范,且重启后消失。

Linux Security Scanner
Linux Security Scanner

Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...

下载

常见坑:

  • class_create 的第二个参数是 owner,必须传 THIS_MODULE,否则模块卸载时 class 释放失败,dmesg 报 "class_destroy called on a class with children"
  • device_create 第四个参数(void *drvdata)可传 NULL,但第五个参数(name)不能含路径或斜杠,否则 udev 创建节点失败,ls /dev 看不到
  • 务必在 module_exit 中按反序调用 device_destroy → class_destroy → unregister_chrdev_region,顺序错会导致 rmmod 卡住或警告

为什么 ioctl 比 read/write 更适合控制类操作

如果需要传递命令、配置寄存器、切换模式等非流式操作,硬塞进 read/write 逻辑会混乱且难维护。此时应实现 ioctl,它专为“控制”设计,参数明确(cmd + arg),且内核已帮你做了用户空间地址校验(对 _IO、_IOR、_IOW 宏定义的 cmd)。

注意事项:

  • 用 _IOWR 宏定义命令时,size 参数必须与用户传入结构体大小严格一致,否则 copy_from_user 可能越界或截断
  • 不要在 ioctl 里调用可能阻塞的函数(如 wait_event_interruptible)而不检查 current->signal->pending,否则用户 Ctrl+C 无法中断 ioctl 调用
  • 若需支持 32/64 位混合环境(比如 x86_64 内核跑 32 位用户程序),必须实现 compat_ioctl,否则 32 位程序调用会直接返回 -ENOTTY

真正麻烦的从来不是注册或读写,而是并发访问时的数据竞争——哪怕只是两个线程同时 write,没加锁就可能把内核缓冲区搞乱。别指望用户态同步,驱动里该用 spin_lock_irqsave 的地方一个都不能少。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

驱动精灵
驱动精灵

驱动精灵基于驱动之家十余年的专业数据积累,驱动支持度高,已经为数亿用户解决了各种电脑驱动问题、系统故障,是目前有效的驱动软件,有需要的小伙伴快来保存下载体验吧!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2288

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1039

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

347

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

426

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

600

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1429

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1237

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ 手册教程
C++ 手册教程

共41课时 | 78.6万人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习