Linux 设备文件的创建和mdev

引子

一、设备类相关知识

(struct driver)、设备(struct device)、设备类(struct class)struct device_attribute

Struct kset是struct kobject的容器,即Struct kset可以成为同一类struct kobject的父亲,而其自身也有kobject成员,因此其又可能和其他kobject成为上一级kset的子成员。

本文无意对sysfs和linux设备驱动模型进行展开,以后再另写文章进行分析。

二、两种创建设备文件的方式

在设备驱动中cdev_add将struct file_operations和设备号注册到系统后,为了能够自动产生驱动对应的设备文件,需要调用class_create和device_create,并通过uevent机制调用mdev(嵌入式linux由busybox提供)来调用mknod创建设备文件。当然也可以不调用这两个接口,那就手工通过命令行mknod来创建设备文件。

三、设备类和设备相关数据结构1include/linux/kobject.h

struct kobject {

const char *name;//名称

struct list_head entry;//kobject链表

struct kobject *parent;//即所属kset的kobject

struct kset *kset;//所属kset

struct kobj_type *ktype;//属性操作接口

};

struct kset {

struct list_head list;//管理同属于kset的kobject

struct kobject kobj;//可以成为上一级父kset的子目录

const struct kset_uevent_ops *uevent_ops;//uevent处理接口

};

假设Kobject A代表一个目录,kset B代表几个目录(包括A)的共同的父目录。则A.kset=B; A.parent=B.kobj.

2include/linux/device.h

struct class {//设备类

const char *name; //设备类名称

struct module *owner;//创建设备类的module

struct class_attribute *class_attrs;//设备类属性

struct device_attribute *dev_attrs;//设备属性

struct kobject *dev_kobj;//kobject再sysfs中代表一个目录

….

struct class_private *p;//设备类得以注册到系统的连接件

};

3drivers/base/base.h

struct class_private {

//该设备类同样是一个kset,包含下面的class_devices;同时在class_subsys填充父kset

struct kset class_subsys;

struct klist class_devices;//设备类包含的设备(kobject)

struct class *class;//指向设备类数据结构,即要创建的本级目录信息

};

4include/linux/device.h

struct device {//设备

struct device *parent;//sysfs/devices/中的父设备

struct device_private *p;//设备得以注册到系统的连接件

struct kobject kobj;//设备目录

const char *init_name;//设备名称

struct bus_type *bus;//设备所属总线

struct device_driver *driver; //设备使用的驱动

struct klist_node knode_class;//连接到设备类的klist

struct class *class;//所属设备类

const struct attribute_group **groups;

}

5drivers/base/base.h

struct device_private {

struct klist klist_children;//连接子设备

struct klist_node knode_parent;//加入到父设备链表

struct klist_node knode_driver;//加入到驱动的设备链表

struct klist_node knode_bus;//加入到总线的链表

struct device *device;//对应设备结构

};

6解释

class_private是class的私有结构,class通过class_private注册到系统中;device_private是device的私有结构,device通过device_private注册到系统中。注册到系统中也是将相应的数据结构加入到系统已经存在的链表中,但是这些链接的细节并不希望暴露给用户,也没有必要暴露出来,,所以才有private的结构。而class和device则通过sysfs向用户层提供信息。

四、创建设备类目录文件

1.在驱动通过cdev_add将struct file_operations接口集和设备注册到系统后,即利用class_create接口来创建设备类目录文件。

led_class = class_create(THIS_MODULE, "led_class");

__class_create(owner, name, &__key);

cls->name = name;//设备类名

cls->owner = owner;//所属module

retval = __class_register(cls, key);

struct class_private *cp;

//将类的名字led_class赋值给对应的kset

kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);//

cp->class_subsys.kobj.kset = class_kset;

//填充class属性操作接口

cp->class_subsys.kobj.ktype = &class_ktype;

cp->class = cls;//通过cp可以找到class

cls->p = cp;//通过class可以找到cp

//创建led_class设备类目录

kset_register(&cp->class_subsys);

//在led_class目录创建class属性文件

add_class_attrs(class_get(cls));

2.继续展开kset_register

kset_register(&cp->class_subsys);

kobject_add_internal(&k->kobj);

// parent即class_kset.kobj,即/sysfs/class对应的目录

parent = kobject_get(kobj->parent);

create_dir(kobj);

//创建一个led _class设备类目录

sysfs_create_dir(kobj);

//该接口是sysfs文件系统接口,代表创建一个目录,不再展开。

3.上述提到的class_kset在class_init被创建

class_kset = kset_create_and_add("class", NULL, NULL);

第三个传参为NULL,代表默认在/sysfs/创建class目录。

五、创建设备目录和设备属性文件

1.利用class_create接口来创建设备类目录文件后,再利用device_create接口来创建具体设备目录和设备属性文件。

led_device = device_create(led_class, NULL, led_devno, NULL, "led");

device_create_vargs

dev->devt = devt;//设备号

dev->class = class;//设备类led_class

dev->parent = parent;//父设备,这里是NULL

kobject_set_name_vargs(&dev->kobj, fmt, args)//设备名”led”

device_register(dev) 注册设备

2.继续展开device_register(dev)

device_initialize(dev);

dev->kobj.kset = devices_kset;//设备所属/sysfs/devices/

device_add(dev)

device_private_init(dev)//初始化device_private

dev_set_name(dev, "%s", dev->init_name);//赋值dev->kobject的名称

怎么能研究出炸药呢?爱迪生不经历上千次的来自失败,怎么能发明电灯呢

Linux 设备文件的创建和mdev

相关文章:

你感兴趣的文章:

标签云: