02、图解字符驱动模块设计思路
一、图解字符驱动模块设计思路
- 用户空间调用
- VFS 层 (虚拟文件系统)
- 字符设备层
- 驱动程序实现
二、应用代码
用户程序通过标准的系统调用(如 open
、read
、write
等)与字符设备交互。例如:
C
int fd = open("/dev/mydevice", O_RDWR);
write(fd, buffer, size);
read(fd, buffer, size);
close(fd);
1
2
3
4
2
3
4
目标:将用户的请求从用户空间传递到内核空间的字符驱动。
三、VFS 层 (虚拟文件系统)
系统调用会通过VFS(虚拟文件系统)进入内核。VFS的作用是把不同文件系统的操作统一管理,具体来说:
- VFS通过
file_operations
结构体找到设备驱动中对应的操作实现。例如,当你读写文件时,VFS会根据这个结构体里的信息找到具体硬件的操作方法。 file_operations
是驱动程序的核心配置表,它记录了驱动如何处理各种操作(如读、写、打开文件等)。可以把它想象成驱动的"操作说明书",告诉操作系统每个动作该调用哪个具体函数。
这样设计的好处是让操作系统不用关心具体硬件细节,只要通过VFS和file_operations
就能兼容不同设备的文件操作。
C
struct file_operations {
.open = my_open,
.read = my_read,
.write = my_write,
.release = my_close,
// 其他操作
};
1
2
3
4
5
6
7
2
3
4
5
6
7
四、驱动程序实现
应用程序通过执行open()
系统调用打开字符设备文件节点后,内核首先解析设备节点的类型标识符(device type)与主设备号(major number)。随后,内核利用主设备号作为索引,定位到字符设备注册表(chrdevs
数组)中对应的驱动注册槽位。该注册表作为Linux字符设备框架的核心数据结构,维护着所有已注册驱动的元信息。通过该槽位的索引值,系统可直接获取驱动在注册阶段通过register_chrdev()
或alloc_chrdev_region()
接口注册的file_operations
(fops)函数指针结构体。该结构体封装了驱动程序实现的系统调用处理函数,包括read()
, write()
, ioctl()
等关键IO操作的底层实现逻辑,这些函数直接映射到设备驱动的硬件交互层,构成用户空间进程与设备控制器间的核心通信接口。
此机制体现了Linux设备模型中"设备-驱动匹配"的核心设计原理:通过设备号空间到驱动注册表的映射关系,结合fops结构体的函数指针动态绑定,实现了用户空间IO请求到设备特定操作的抽象化转换与高效路由。
五、驱动流程
- 主次设备号:dev_t类型变量设备号、MAJOR、MINOR
- 设备号的分配:alloc_chrdev_region
- 方法操作集:cdev_init、file_operations、cdev_add
- 节点的创建:class_create、device_create