Linux 设备文件的创建和mdev

Posted 吴跃前

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux 设备文件的创建和mdev相关的知识,希望对你有一定的参考价值。

引子

本文是嵌入式企鹅圈开篇 -- linux 字符设备驱动剖析》的姐妹篇,在上述文章里面我们详细描述了字符设备驱动框架涉及的驱动注册、通过设备文件来访问驱动等知识,并明确通过 device_create 接口并结合 mdev 来创建设备文件,但没有展开这个知识点。本文将从代码级去理解 Linux 设备类和设备文件的创建过程。通过这两篇文章,我们将可以对 linux 字符设备驱动的机制和脉络有全面的认识。

以下程序分析没有缩进,编辑了好几次都不行,耐心点才能跟踪完整个代码:-)


一、设备类相关知识

设备类是虚拟的,并没有直接对应的物理实物,只是为了更好地管理同一类设备导出到用户空间而产生的目录和文件。整个过程涉及到sysfs文件系统,该文件系统是为了展示linux设备驱动模型而构建的文件系统,是基于ramfslinux根目录中的/sysfs即挂载了sysfs文件系统。

Struct kobject数据结构是sysfs的基础,kobjectsysfs中代表一个目录,而linux的驱动(struct driver)、设备(struct device)、设备类(struct class)均是从kobject进行派生的,因此他们在sysfs中都对应于一个目录。而数据结构中附属的struct device_attributedriver_attributeclass_attribute等属性数据结构在sysfs中则代表一个普通的文件。

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

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


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

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


三、设备类和设备相关数据结构

1include/linux/kobject.h

struct kobject

const char *name;//名称

struct list_head entry;//kobject链表

struct kobject *parent;//即所属ksetkobject

struct kset *kset;//所属kset

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

;

struct kset

struct list_head list;//管理同属于ksetkobject

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;//kobjectsysfs中代表一个目录

….

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


四、创建设备类目录文件

1.在驱动通过cdev_addstruct 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);

//填充class_subsys所属的父ksetket:sysfs/class.

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

深入理解Linux字符设备驱动

深入理解Linux字符设备驱动

自动创建设备节点-12

Linux设备文件自动生成

hotplug/mdev机制

Linux之udev,mdev,devfs,sysfs,uevent之间关系