目录
一、前言
二、实现设备节点的自动生成
2.1 创建设备节点的方法
2.2 基本函数
2.2.1 class_create()
2.2.2 class_destroy()
2.2.3 device_create()
2.2.4 device_destroy()
2.3 自动创建节点的步骤
step1:使用class_create函数创建一个class的类。
step2:使用device_create函数在我们创建的类下面创建一个设备。
step3: 移除设备
step4: 移除逻辑类
三、编译运行
step1:编译
step2:插入内核中
step3:查看/dev和/sys/class/目录下是否自动生成相应文件
step4: 测试读写
四、小结
五、往期内容
脚本下载链接(Github)
[Linux驱动开发二]文章中只实现了最简单的字符设备,仍然遗留了若干问题,如无法自动生
成设备节点以及读写功能没有具体实现,本篇文章主要为了解决无法自动生成设备节点的问题。
创建设备节点的方法大致分为两种,第一种是使用mknod手工创建:"mknod [文件名] [类型]
[主设备号] [次设备号]",第二种是自动创建设备节点:自动创建设备节点是利用udev(mdev)来实现
设备文件的自动创建。第二种也是接下来重点介绍的方法。
宏class_create()用于动态创建设备的逻辑类,该函数的执行效果就是在目录/sys/class
下创
建一个新的文件夹,此文件夹的名字为此函数的第二个输入参数,但此文件夹是空的。宏
class_create()在实现时,调用了函数__class_create(),作用和函数__class_create()基本相同。其定义如下:
#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \
__class_create(owner, name, &__key); \
})
class_create输入参数说明:
1)参数owner是一个struct module结构体类型的指针,指向函数__class_create()即将创建的struct class 类型对象的拥有者,一般赋值为THIS_MODULE;
2)参数name是char类型的指针,表示即将创建的struct class变量的名字,用于给struct class的name字段赋值。
class_create输出参数说明:
宏class_create()与__class_create()的返回值相同,都是个指向结构体class的指针即新创建
的逻辑类。
代码示例:
hc_cls = class_create(THIS_MODULE, "hc_dev");
if(!hc_cls){
printk(KERN_WARNING "fail create class");
ret = PTR_ERR(hc_cls);
}
函数class_destroy()用于删除设备的逻辑类,即从Linux内核系统中删除设备的逻辑类,该函
数的执行效果是删除函数__class_create()或宏class_create()在目录/sys/class下创建的逻辑类对应
的文件夹。其基本定义如下;
void class_destroy(struct class *cls)
class_destroy输入参数说明:
函数class_destroy()的输入参数是struct class结构体类型的变量,代表设备的逻辑类。
class_destroy输出参数说明:
函数class_destroy()的返回值是void类型的变量,不返回任何值。
函数device_create()用于动态创建逻辑设备,对新的逻辑设备进行相应初始化,然后将此逻辑
设备加入到Linux内核系统的设备驱动程序模型中。该函数会自动地在/sys/devices/virtual目录下创
建新的逻辑设备目录,在/dev目录下创建与逻辑类对应地设备文件。其基本定义如下:
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
device_create输入参数说明:
1)参数class代表要创建在哪个类下面;
2)参数parent代表此设备的父设备,一般为NULL;
3) 参数devt代表设备号;
4)参数drvdata代表设备可能会使用的一些数据,一般为NULL;
5)参数fmt是设备名字,如果设置fmt=xxx的话,就会生成/dev/xxx这个设备文件。返回值就
是创建好的设备。
device_create输出参数说明:
函数device_create()的返回值是struct device结构体类型的指针,指向新创建的逻辑设备。
代码示例
device_create(hc_cls, NULL, MKDEV(hello_major, hello_minor + i), NULL, "hc_dev%d", i);
函数device_destroy()用于从Linux内核系统设备驱动程序模型中移除一个设备,并删
除/sys/devices/virtual目录下对应的设备目录以及/dev目录下对应的设备文件。其基本定义如下:
void device_destroy(struct class *cls, dev_t devt);
device_destroy的输入参数说明:
1)函数device_destroy()第一个输入参数是struct class类型的变量,代表与代注销的逻辑设备相关的逻辑类;
2)devt参数是逻辑设备的设备号,它与第一个参数共同确定了一个逻辑设备。
device_destroy的输出参数说明:
函数device_destroy()的输出返回值为void类型的变量,不返回任何值。
#include
/* 添加一个类的指针,后续通过class_create()创建的类就保存在这个指针中 */
struct class *hc_class;
hc_cls = class_create(THIS_MODULE, "hc_dev")
if (!cls_class){
printk(KERN_WARNING "fail create class);
ret = PTR_ERR(hc_cls);
}
/*
hello_nr_devs表示设备数
hello_major为主设备号
hello_minor为次设备号
hc_dev为文件名称
*/
for (int i = 0; i < hello_nr_devs; i++){
device_create(hc_cls, NULL, MKDEV(hello_major, hello_minor + i), NULL, "hc_dev%d", i);
}
for (i = 0; i < hello_nr_devs; i++){
device_destroy(hc_cls, MKDEV(hello_major, hello_minor + i));
}
class_destroy(hc_cls);
本章节成功解决了之前得字符设备无法自动生成设备节点得问题,目前问题已经得到解决,
接下来的章节将会对设备的读写功能进行进一步开发。
[Linux驱动开发一] 最简单的内核模块
[Linxu驱动开发二] 最简单的字符设备