kset是具有相同类型的kobject的集合,在sysfs体系中体现为一个目录,在内核中有一个网上有一个非常经典的图,反应出kobject和kset的关系。
kobject对应于sysfs文件系统的一个目录,该目录可以有一些设备属性相关的文件。
kset相同类型的kobject的集合,也是对应于sysfs文件系统的一个目录,其子目录,也就是kobject的目录。
- struct kset {
- struct list_head list; //连接kset中所有的kobject的链表
- spinlock_t list_lock; //访问时候加锁
- struct kobject kobj; //连接kobject
- const struct kset_uevent_ops *uevent_ops;//主要是热插拔事件
- };
由上面的数据类型和图可以看出,kset和kobject的基本关系。
- int kset_register(struct kset *k)
- {
- int err;
- if (!k)
- return -EINVAL;
- kset_init(k); //kset一些初始化
- err = kobject_add_internal(&k->kobj); //添加kobject到kset中
- if (err)
- return err;
- kobject_uevent(&k->kobj, KOBJ_ADD); //初始化evnet
- return 0;
- }
可以看出,它只是把kset中的kobject连到系统中,向用户空间发一个KOBJ_ADD。
- void kset_init(struct kset *k)
- {
- kobject_init_internal(&k->kobj);
- INIT_LIST_HEAD(&k->list);
- spin_lock_init(&k->list_lock);
- }
向内核注销kset函数
- void kset_unregister(struct kset *k)
- {
- if (!k)
- return;
- kobject_put(&k->kobj);
- }
在linux系统中,当系统的环境发生变化时,如添加kset到系统,移动kobject都会从内核空间发送到用户控件,这个是热插拔事件,那么相应的处理程序会被调用,这个处理程序会调用加载驱动,创建设备节点等来响应。
- struct kset_uevent_ops {
- int (* const filter)(struct kset *kset, struct kobject *kobj);
- const char *(* const name)(struct kset *kset, struct kobject *kobj);
- int (* const uevent)(struct kset *kset, struct kobject *kobj,
- struct kobj_uevent_env *env);
- };
这三个函数有什么作用
1、filter:决定了是否会将热插拔事件传递到用户控件。返回0,不传递,返回1,传递
2、name:用于将字符串传递给用户控件的热插拔处理程序
3、uevent:将用户空间需要的参数添加到环境变量中。
下面是一个kset和kobject结合的例子
- 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,"%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",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()
- {
- 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;//指向父目录,由于有结构的变化会触发热插拔事件
- kset_register(&kset_c);
- return 0;
- }
-
- int kset_test_exit()
- {
- printk("kset test exit.\n");
- kset_unregister(&kset_p);
- kset_unregister(&kset_c);
- return 0;
- }
-
- module_init(kset_test_init);
- module_exit(kset_test_exit);
阅读(3776) | 评论(0) | 转发(5) |