Linux 设备文件的创建和mdev
Posted 吴跃前
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux 设备文件的创建和mdev相关的知识,希望对你有一定的参考价值。
引子
一、设备类相关知识
设备类是虚拟的,并没有直接对应的物理实物,只是为了更好地管理同一类设备导出到用户空间而产生的目录和文件。整个过程涉及到sysfs文件系统,该文件系统是为了展示linux设备驱动模型而构建的文件系统,是基于ramfs,linux根目录中的/sysfs即挂载了sysfs文件系统。
Struct kobject数据结构是sysfs的基础,kobject在sysfs中代表一个目录,而linux的驱动(struct driver)、设备(struct device)、设备类(struct class)均是从kobject进行派生的,因此他们在sysfs中都对应于一个目录。而数据结构中附属的struct device_attribute、driver_attribute、class_attribute等属性数据结构在sysfs中则代表一个普通的文件。
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);
//填充class_subsys所属的父kset:ket: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字符设备驱动