[Linux驱动开发三]实现自动生成设备节点

目录

一、前言

二、实现设备节点的自动生成

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驱动开发二]文章中只实现了最简单的字符设备,仍然遗留了若干问题,如无法自动生

成设备节点以及读写功能没有具体实现,本篇文章主要为了解决无法自动生成设备节点的问题。

二、实现设备节点的自动生成

2.1 创建设备节点的方法

        创建设备节点的方法大致分为两种,第一种是使用mknod手工创建:"mknod [文件名] [类型]

[主设备号] [次设备号]",第二种是自动创建设备节点:自动创建设备节点是利用udev(mdev)来实现

设备文件的自动创建。第二种也是接下来重点介绍的方法。

2.2 基本函数

2.2.1 class_create()

        宏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);
}

2.2.2 class_destroy()

        函数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类型的变量,不返回任何值。

2.2.3 device_create()

        函数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);

2.2.4 device_destroy()

        函数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类型的变量,不返回任何值。

2.3 自动创建节点的步骤

[Linux驱动开发三]实现自动生成设备节点_第1张图片

step1:使用class_create函数创建一个class的类。

#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);
}

step2:使用device_create函数在我们创建的类下面创建一个设备。

/*
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);
}

step3: 移除设备

for (i = 0; i < hello_nr_devs; i++){
    device_destroy(hc_cls, MKDEV(hello_major, hello_minor + i));
}

step4: 移除逻辑类

class_destroy(hc_cls);

 三、编译运行

step1:编译

[Linux驱动开发三]实现自动生成设备节点_第2张图片

step2:插入内核中

step3:查看/dev和/sys/class/目录下是否自动生成相应文件

[Linux驱动开发三]实现自动生成设备节点_第3张图片

[Linux驱动开发三]实现自动生成设备节点_第4张图片

step4: 测试读写

 [Linux驱动开发三]实现自动生成设备节点_第5张图片

四、小结

        本章节成功解决了之前得字符设备无法自动生成设备节点得问题,目前问题已经得到解决,

接下来的章节将会对设备的读写功能进行进一步开发。

五、往期内容

        [Linux驱动开发一] 最简单的内核模块

        [Linxu驱动开发二] 最简单的字符设备        

你可能感兴趣的:(Linux驱动编程,驱动开发,linux,运维)