kset是具有相同类型kobject集合,在sysfs中体现为一目录(目录包含目录)
这三个函数的功能:
Filter:决定是否将事件传递到用户空间,如filter返回0,将不传递事件
Name:负责将相应字符串传递给用户空间的热插拔处理程序
Uevent:将用户空间需要的参数添加到环境变量中(如说明到底为添加或删除所造成的热拔插事件,即事件类型)
——————/
/12 # insmod kset.ko
kset_c
ACTION=add
DEVPATH=/kset_p/kset_c
SUBSYSTEM=kset_name
/sys/kset_p # ls
kset_c
/12 # rmmod kset
kset_c
ACTION=remove
DEVPATH=/kset_p/kset_c
SUBSYSTEM=kset_name
kset_filter返回0:
/12 # insmod kset.ko
kset_c
struct kset {
struct list_head list; //连接该kset中所有kobject链表头
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops; //处理热插拔事件操作集合
};
int kset_register(struct kset *kset) //注册一kset
void kset_unregister(struct kset *kset) //注销一kset
Linux系统中,当配置发生变化,如添加kset、移动kobject,一个通知会从内核空间发送到用户空间,即热插拔事件。热插拔事件会导致用户空间相应处理程序(如udev、mdev)被调用,这些处理程序会通过加载驱动、创建设备节点等响应
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);
};
当kset所管理的kobject和kset状态发生变化(如被加入,移动),这三个函数将被调用
这三个函数的功能:
Filter:决定是否将事件传递到用户空间,如filter返回0,将不传递事件
Name:负责将相应字符串传递给用户空间的热插拔处理程序
Uevent:将用户空间需要的参数添加到环境变量中(如说明到底为添加或删除所造成的热拔插事件,即事件类型)
struct kobj_uevent_env {
char *envp[UEVENT_NUM_ENVP];
int envp_idx;
char buf[UEVENT_BUFFER_SIZE];
int buflen;
};
uevent返回值正常时为0,若返回非零值将终止热插拔事件的产生
——————/
#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>
#include <linux/kobject.h>
struct kset * kset_p;
struct kset kset_c;
int kset_filter(struct kset *kset, struct kobject *kobj)
{
printk("%s\n",kobj->name);
return 1;
}
const char *kset_name(struct kset *kset, struct kobject *kobj)
{
static char buf[20];
sprintf(buf,"%s","kset_name");
return buf;
}
int kset_uevent(struct kset *kset, struct kobject *kobj,struct kobj_uevent_env *env)
{
int i = 0;
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,
};
struct kobj_type ktype;
static int kset_test_init(void)
{
kset_p=kset_create_and_add("kset_p", &uevent_ops,NULL);
// kset_create、kset_register
kobject_set_name(&kset_c.kobj,"kset_c");
kset_c.kobj.kset = kset_p; //*****
kset_c.kobj.ktype = &ktype; //不起作用,但必须提供,否则oops
kset_register(&kset_c);
return 0;
}
static void kset_test_exit(void)
{
kset_unregister(kset_p);
kset_unregister(&kset_c);
}
module_init(kset_test_init);
module_exit(kset_test_exit);
MODULE_LICENSE("GPL");
——————/
/12 # insmod kset.ko
kset_c
ACTION=add
DEVPATH=/kset_p/kset_c
SUBSYSTEM=kset_name
/sys/kset_p # ls
kset_c
/12 # rmmod kset
kset_c
ACTION=remove
DEVPATH=/kset_p/kset_c
SUBSYSTEM=kset_name
kset_filter返回0:
/12 # insmod kset.ko
kset_c