sysfs 把连接在系统上的设备和总线组织成为一个分级的文件,展示设备驱动模型中各组件的层次关系
总线bus:类型class:设备device
此处的device是系统注册上的device,是bus、class下的device的子集。
在/sys/bus 的 pci 等子目录下,又会在分出 drivers 和 devices 目录,而 devices 目录中的文件是对/sys/devices 目录中文件的符号链接。同样地,/sys/class 目录下包含许多对/sys/devices 下文件的链接。
struct device:
1、系统中的任一设备在设备模型中都由一个 device 对象描述,但不单独使用
2、内嵌kobject来组织驱动层次。
3、device_register()函数将一个新的 device 对象插入设备模型,并自动在/sys/devices 下创建一个对应的目录。
struct device {
struct klist klist_children; // 设备列表中的孩子列表
struct klist_node knode_parent;// 兄弟节点
struct klist_node knode_driver; // 驱动结点
struct klist_node knode_bus; // 总线结点
struct device * parent; // 指向父设备
struct kobject kobj; // 内嵌一个 kobject 对象
char bus_id[BUS_ID_SIZE];// 总线上的位置
struct bus_type * bus; // 总线
struct device_driver *driver;// 使用的驱动
void *driver_data; // 驱动私有数据
void *platform_data; //平台特定的数据
void *firmware_data; //固件特定的数据(如 ACPI、BIOS 数据)
void (*release)(struct device * dev); // 释放设备方法
};
struct device_driver:
1、内嵌的 kobject
2、内核提供类似的函数用于操作 device_driver 对象。如 get_driver()增加引用计数,driver_register()用于向设备模型插入新的 driver 对象,同时在 sysfs 文件系统中创建对应的目录。
struct device_driver
{
const char * name; //设备驱动程序的名称
struct bus_type * bus; //总线
struct completion unloaded;
struct kobject kobj;//内嵌的 kobject 对象
struct klist klist_devices;
struct klist_node knode_bus;
struct module * owner;
int (*probe) (struct device * dev); //指向设备探测函数
int (*remove) (struct device * dev); //指向设备移除函数
void (*shutdown) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state);
int (*resume) (struct device * dev);
};
struct bus_type
1、内嵌subsystem
2、包含处理热插拔、即插即拔和电源管理事件的函数
1 struct bus_type
2 {
3 const char * name;//总线类型的名称
4
5 struct subsystem subsys;//与该总线相关的 subsystem
6 struct kset drivers;//所有与该总线相关的驱动程序集合
7 struct kset devices;//所有挂接在该总线上的设备集合
8 struct klist klist_devices;
9 struct klist klist_drivers;
10
11 struct bus_attribute * bus_attrs;//总线属性
12 struct device_attribute * dev_attrs;//设备属性
13 struct driver_attribute * drv_attrs; //驱动程序属性
14
15 int (*match)(struct device * dev, struct device_driver * drv);
16 int (*uevent)(struct device *dev, char **envp,
17 int num_envp, char *buffer, int buffer_size);//事件
18 int (*probe)(struct device * dev);
19 int (*remove)(struct device * dev);
20 void (*shutdown)(struct device * dev);
21 int (*suspend)(struct device * dev, pm_message_t state);
22 int (*resume)(struct device * dev);
23 };
struct class
1、设备类
2、内嵌sub system
3、包括用于处理热插拔、即插即拔和电源管理事件的函数
struct class_device
{
struct list_head node;
struct kobject kobj;//内嵌的 kobject
struct class * class; //所属的类
dev_t devt; // dev_t
struct class_device_attribute *devt_attr;
struct class_device_attribute uevent_attr;
struct device * dev; //如果存在,创建到/sys/devices 相应入口的符号链接
void * class_data; //私有数据
struct class_device *parent; //父设备
void (*release)(struct class_device *dev);
int (*uevent)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
char class_id[BUS_ID_SIZE]; //类标识
};
kobject:
1、注册的 kobject 对象都对应于sysfs 文件系统中的一个目录。
2、这个数据结构使所有设备在底层都具有统一的接口。
3、父对象指向kset内嵌kobject
struct kobject
{
char *k_name;
char name[KOBJ_NAME_LEN]; //对象名称
struct kref kref; //对象引用计数
struct list_head entry; //用于挂接该 kobject 对象到 kset 链表
struct kobject *parent; //指向父对象的指针
struct kset *kset; //所属 kset 的指针
struct kobj_type *ktype; //指向对象类型描述符的指针
struct dentry *dentry; //sysfs 文件系统中与该对象对应的文件节点入口
};
kset:
1、具有相同类型的 kobject 的集合(一个双向循环链表)
2、kset 数据结构还内嵌了一个 kobject 对象(kobj 成员表示),所有属于这个 kset的 kobject 对象的 parent 均指向这个内嵌的对象。
3、kobject 被创建或删除时会产生事件(event),kobject 所属的 kset 将有机会过滤事件或为用户空间添加信息。
struct kset
{
struct subsystem * subsys; //所在的 subsystem 的指针
struct kobj_type * ktype; //指向该 kset 对象类型描述符的指针
struct list_head list; //用于连接该 kset 中所有 kobject 的链表头
spinlock_t list_lock;
struct kobject kobj; //嵌入的 kobject
struct kset_uevent_ops * uevent_ops;//事件操作集
};
kset 的uevent_ops 成员是执行该 kset 事件操作集 kset_uevent_ops 的指针
1、filter()函数用于过滤掉不需要导出到用户空间的事件,
2、uevent()函数用于导出一些环境变量给用户的热插拔处理程序
struct kset_uevent_ops
{
int (*filter)(struct kset *kset, struct kobject *kobj);//事件过滤
const char *(*name)(struct kset *kset, struct kobject *kobj);
int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size);//环境变量设置
};
subsystem :
1、kset 的集合,对 应 于 /sysfs/ 目录 。
2、内嵌 kset ,keset通过指向内嵌kset 加入到该 subsystem。
struct subsystem
{
struct kset kset; //内嵌的 kset 对象
struct rw_semaphore rwsem; //互斥访问信号量
};