Linux驱动的kobj/kset/bus/dev/drv/class
创始人
2025-05-31 13:05:52
0

sysfs文件系统是基于RAM实现的文件系统,以下操作便是基于sysfs文件系统。

一、kobject和kset和kobject_uevent()

1)kobject

kobject表示一个内核对象,在使用时通常是嵌在某一内核对象的数据结构中,比如字符设备cdev定义的内核对象也嵌入了。

struct kobject {/*用来表示内核对象的名称,如果该内核对象加入系统,那么它的name会出现在sysfs文件系统中,表现形式是一个新的目录名字*/const char        *name;/*将一系列的内核对象构成链表*/struct list_head    entry;/*指向该内核对象的上层节点,通过该成员构建内核对象的层次化关系*/struct kobject        *parent;/*当前内核对象所属的kset对象指针,kset可以容纳一系列同类型的kobject对象*/struct kset        *kset;/*定义了该内核对象的一组sysfs文件系统相关的操作函数和属性。同时,内核通过ktype成员将kobject对象的sysfs文件操作(show和store)与其属性文件关联起来。*/const struct kobj_type    *ktype;/*用来表示该内核对象在sysfs文件系统中对应的目录项的实例*/struct kernfs_node    *sd;/*内核通过该成员追踪内核对象的生命周期*/struct kref        kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASEstruct delayed_work    release;
#endif/*表示该kobject代表的内核对象的初始化状态,1表示对象已被初始化,0表示未被初始化*/unsigned int state_initialized:1;/*表示该kobject代表的内核对象有没有在sysfs中建立一个入口点*/unsigned int state_in_sysfs:1;unsigned int state_add_uevent_sent:1;unsigned int state_remove_uevent_sent:1;/*如果kobect隶属于某一个kset,那么它的状态变化可能导致其所在的kset对象向用户空间发送event消息。该成员便用来表示当该kobject状态发生变化时,是否让其所在的kset向用户空间发送event消息,值1表示不让kset发送。*/unsigned int uevent_suppress:1;
};

2)kset

kset可以认为是一组kobject组合。kset本身也是一个内核对象,所以需要内嵌一个kobect对象。

struct kset_uevent_ops {int (* const filter)(struct kobject *kobj);const char *(* const name)(struct kobject *kobj);int (* const uevent)(struct kobject *kobj, struct kobj_uevent_env *env);
};struct kset {/*用来将其中的kobect对象构建成链表*/struct list_head list;/*对kset上的list链表进行访问操作时用来作为互斥保护*/spinlock_t list_lock;/*代表当前kset内核对象的kobject变量*/struct kobject kobj;/*当kset中的某些kobject对象发送状态变化需要通知用户空间时,可以调用其中的函数来完成*/const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;

3)kobject_uevent()

Linux设备模型中一个非常重要的功能便是对设备热插拔的支持,能够在设备动态加入或者移除系统时能检查到,然后通知用户去加载或者卸载该设备所对应的驱动。具体到底层的实现细节上,热插拔在内核中通过kobject_uevent()函数来实现,它通过发送一个uevent消息和调用call_usermodehelper来与用户空间进程沟通;它是udev等工具赖以工作的基石,如果系统中有守护进程udevd,那么它应一直监听kobject_uevent通过netlink广播出去的uevet数据包。

/*这列枚举值定义了kset对象的一些状态变化*/
enum kobject_action {KOBJ_ADD,  //表明向系统添加一个ksetKOBJ_REMOVE,KOBJ_CHANGE,KOBJ_MOVE,KOBJ_ONLINE,KOBJ_OFFLINE,KOBJ_BIND,KOBJ_UNBIND,
};
int kobject_uevent(struct kobject *kobj, enum kobject_action action)
{return kobject_uevent_env(kobj, action, NULL);
}

比如,可以通过kobject_uevent将内核对象kobject的状态变化通知用户程序:

static ssize_t mytest_store(struct kobject *kobj,struct kobj_attribute *attr, const char *buf, size_t count)
{...flag = buf[0] - `0`;switch (flag) {case 0:kobject_uevent(kobj, KOBJ_ADD);break;case 1:kobject_uevent(kobj, KOBJ_REMOVE);break;default:break;}return count;
}static struct kobj_attribute mytest_attr =__ATTR(active, 0644, mytest_show, mytest_store);

二、bus_type/device/device_driver/class

1)内核启动过程中的一些初始化

static int bus_uevent_filter(struct kobject *kobj)
{const struct kobj_type *ktype = get_ktype(kobj);if (ktype == &bus_ktype)/*如果要求发送uevent消息的kobject对象类型是bus_type,那么返回1,意味着uevent消息将会发送到用户空间。所以这里的bus_uevent_ops使得bus_kset只用来发送bus类型的内核对象产生的uevent消息。*/return 1;return 0;
}static const struct kset_uevent_ops bus_uevent_ops = {.filter = bus_uevent_filter,
};int __init buses_init(void)
{/*1)创建一个名为bus的kset,并将其加入到sysfs文件系统树中(/sys/bus),这里需要注意bus_uevent_ops定义了当"bus"这个kset中有状态变化时,用来通知用户空间uevent消息的操作集。由于当某个kset中有状态变化时,如果需要向用户空间发送event消息,将由该kset的顶层kset来指向,因为bus_kset是系统中所有bus subsystem最顶层的kset,所以bus中的uevent最终会汇集到这里的bus_uevent_ops中。这个操作函数集中只定义了一个filter操作,意味着当“bus”kset中发送状态变化时,会通过bus_uevent_ops中的filter函数先行处理,以决定是否通知用户空间。2)这里创建的"bus总线将是系统中所有后续注册总线的祖先。"*/bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);if (!bus_kset)return -ENOMEM;system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);if (!system_kset)return -ENOMEM;return 0;
}int __init devices_init(void)
{/*系统中的每个设备都是一个struct device对象,为容纳所有这些设备定义了一个devices_kset*/devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);....../*内核将系统中的设备分为block和char二类,每类对应一个内核对象,分别为sysfs_dev_block_kobj和sysfs_dev_char_kobj*/dev_kobj = kobject_create_and_add("dev", NULL);......sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);......sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);......
}int __init classes_init(void)
{class_kset = kset_create_and_add("class", NULL, NULL);if (!class_kset)return -ENOMEM;return 0;
}void __init driver_init(void)
{......devices_init();buses_init();classes_init();......
}

2)从总线的角度看,总线设备驱动三者的关系

如下所示,其中struct kset sybsys标识了系统中当前总线对象与bus_kset间的隶属关系,而struct kset *drivers_kset和struct kset *devices_kset则是在向系统注册当前新总线时动态生成的容纳该总线上所有驱动和设备的kset,与此对应,二个klist成员则以链表的形式将该总线上的所有驱动与设备链接到一起

struct subsys_private {/*用来表示bus所在的子系统,在内核中所有通过bus_register注册进系统的bus所在的kset都将指向bus_kset,换句话说bus_kset是系统中所有bus内核对象的容器,而新注册的bus本身也是一个kset型对象*/struct kset subsys/*表示该bus上所有设备的一个集合*/struct kset *devices_kset;struct list_head interfaces;struct mutex mutex;/*表示该bus上所有驱动的一个集合*/struct kset *drivers_kset;/*表示该bus上所有设备的链表*/struct klist klist_devices;/*表示该bus上所有驱动的链表*/struct klist klist_drivers;struct blocking_notifier_head bus_notifier;/*用来表示向系统中某一总线注册某一设备或驱动的时候,是否进行设备与驱动的绑定操作*/unsigned int drivers_autoprobe:1;/*指向与struct bus_type_private对象相关联的bus*/struct bus_type *bus;struct kset glue_dirs;struct class *class;
};

3)class

相对于设备device,class是一种更高层次的抽象,用户对设备进行功能上的划分。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...