Kset
/*******************************************************************
*Kset是具有相同类型的kobject集合,在sysfs中体现为一个目录,
*在内核中用kset数据结构表示。
*******************************************************************/
struct kset{
struct list_head list;//连接该kset中所有kobject的链表头
spinlock_t list_lock;
struct kobject kobj;//内嵌的kobject
struct kset_uevent_ops *uevent_ops;//处理热插拔事件的操作集合
};
Kset操作
- 在内核中注册一个kset
int kset_register(struct kset *kset)
- 从内核中注销一个kset
void kset_unregister(struct kset *kset)
热插拔事件
在linux系统中,当系统配置发生变化时。如:添加kset到系统;移动kobject,一个通知会从内核空间发送到用户空间,这就是热插拔事件。
热插拔事件会导致用户空间中相应的处理程序(如:udev、mdev)被调用,这些处理程序会通过加载驱动程序,创建设备节点等来响应热插拔事件。
Kset_uevent_ops操作集合
/*******************************************************************
*当该set所管理的kobject和kset状态发生变化时(被加入、被移动)
*这三个函数将被调用
*******************************************************************/
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,struct kobj_uevent_env *env);
};
- filter:决定是否将事件传递给用户空间。如果filter返回0,将不传递事件。
- name:用于将字符串传递给用户空间的热插拔处理程序。
- uevent:将用户空间需要的参数添加到环境变量中。
Kset源码!!!!
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
struct kset kset_p;
struct kset kset_c;
int kset_filter(struct kset *kset,struct kobject *kobj){
printk("filter : kobj %s\n",kobj->name);
return 1;
}
const char *kset_name(struct kset *kset,struct kobject *kobj){
static char buf[20];
printk("name : kobj %s\n",kobj->name);
sprintf(buf,"buf is %s","kset_name");
return buf;
}
int kset_uevent(struct kset *kset,struct kobject *kobj,struct kobj_uevent_env *env){
int i = 0;
printk("uevent: kobj %s\n",kobj->name);
while(i < env->envp_idx){
printk("%s \n",i,env->envp[i]);
i++;
}
return 0;
}
struct kset_uevent_ops uevent_ops = {
.filter = kset_filter,
.name = kset_name,
.uevent = kset_uevent
};
int kset_test_init(void){
printk("kset test init!!\n");
kobject_set_name(&kset_p.kobj,"kset_p");
kset_p.uevent_ops = &uevent_ops;
kset_register(&kset_p);
kobject_set_name(&kset_c.kobj,"kset_c");
kset_c.kobj.kset = &kset_p;//设置父类使用kobj中的kset
kset_register(&kset_c);
return 0;
}
void kset_test_exit(void){
printk("kset test exit!!\n");
kset_unregister(&kset_p);
kset_unregister(&kset_c);
}
MODULE_LICENSE("GPL");
module_init(kset_test_init);
module_exit(kset_test_exit);