Linux字符设备驱动
一、字符设备
字符设备是指在I/O传输过程中以字符为单位进行传输的设备,是面向流的设备,常见的字符设备有鼠标、键盘、串口、控制台和LED等。
字符设备会在linux系统的/dev目录下对应一个设备文件。字符设备可以使用与普通文件相同的文件操作命令对字符设备文件进行操作,例如打开、关闭、读、写等。
二、字符设备驱动模型
Linux系统下字符设备驱动主要有2部分:用户态设备文件和内核态驱动中文件操作函数(见图2.1)。用户态的进程想和硬件设备交互时,首先要通过系统调用操作(read()、write()、ioctl()等)字符设备文件,字符设备驱动然后调用file_operations 中注册的操作函数和硬件交互。
三、字符设备驱动构建
Linux系统下构建字符设备驱动主要有部分要实现:驱动初始化、设备操作、驱动注销(见图3.1)。
a. 驱动初始化:
需要完成cdev的分配、cdev初始化、注册cdev及硬件设备初始化。
b. 设备操作:
需要填充 struct file_operations 结构体中断的操作函数,实现 struct file_operations 结构体中
的read()、write()和ioctl()等函数是驱动设计的主体工作。
c. 驱动注销:
即释放设备号、删除、注销cdev。
即释放设备号、删除、注销cdev。
3.1 struct cdev
<include/linux/cdev.h>
1 |
|
3.2 cdev初始化
对于struct cdev,内核在头文件linux/cdev.h中提供了相应操作接口:
3.2.1 为cdev分配内存
1 |
|
3.2.2 初始化cdev
初始化cdev的成员变量,并建立cdev和file_operations之间的关联。
1 |
|
3.2.3 注册cdev设备对象
注册cdev设备对象,添加到系统字符设备列表中。
1 |
|
3.2.4 设备号申请
一个字符设备有一个主设备号和一个次设备号。主设备号用来标识与设备文件相连的驱动程序,用来反映设备类型。次设备号被驱动程序用来辨别操作的是哪个设备,用来区分同类型的设备。
linux内核中,设备号用dev_t来描述:
内核在头文件 linux/fs.h中提供了几个方便操作的宏定义来实现dev_t:
1 |
|
1 |
|
3.2.4.1 - 静态申请设备号
1 |
|
3.2.4.2 - 动态分配设备号
1 |
|
3.2.4.3 创建设备文件
利用cat /proc/devices查看申请到的设备名,设备号。
a. 使用mknod手工创建:
mknod filename type major minor
b. 自动创建设备节点:
利用udev(mdev)来实现设备文件的自动创建,首先应保证支持udev(mdev),由busybox配置。在驱动初始化代码里调用class_create为该设备创建一个class,再为每个设备调用device_create创建对应的设备。
3.3 file_operations *fops
Linux下一切皆文件,字符设备也是抽象成设备文件,struct cdev 中的file_operations结构体中的成员函数是字符设备程序设计的主题内容,这些函数实际会在用户层程序进行Linux的open()、close()、write()、read()等系统调用时最终被调用。
文件的操作接口结构:
1 |
|
3.4 cdev注销
3.4.1 释放设备号
1 |
|
3.4.2 注销cdev
将cdev对象从系统中移除
1 |
|
3.4.3 释放cdev内存
1 |
|
Linux字符设备驱动
https://leo-hou.github.io/2022/03/20/Linux字符设备驱动/