linux设备驱动模型之 kset原理与实例分析

1、 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; //处理热插拔事件的操作集合

}

2、 Kset操作

1)int kset_register(struct kset *kset)

在内核中注册一个kset

2)void kset_unregister(struct kset *kset)

从内核中注销一个kset

3、 热插拔事件

在Linux系统中,当系统配置发生变化时,如:添加kset到系统;移动kobject, 一个通知会从内核空间发送到用户空间,这就是热插拔事件。热插拔事件会导致用户空间中相应的处理程序(如udev,mdev)被调用, 这些处理程序会通过加载驱动程序, 创建设备节点等来响应热插拔事件。

4、热插拔事件操作集合

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);

}

kset_uevent_ops这三个函数什么时候调用?

当该kset所管理的kobject和kset状态发生变化时(如被加入,移动),这三个函数将被调用。(例:kobject_uevent调用)

这三个函数的功能是什么?

1)filter:决定是否将事件传递到用户空间。如果filter返回0,将不传递事件。(例: uevent_filter)

2)name:用于将字符串传递给用户空间的热插拔处理程序。

3)uevent:将用户空间需要的参数添加到环境变量中。(例:dev_uevent)

5、 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> #include <linux/kobject.h> MODULE_AUTHOR("yinjiabin"); MODULE_LICENSE("GPL"); struct kset *kset_p; struct kset kset_c; /* 函数声明 */ void obj_test_release(struct kobject *); ssize_t kobj_test_show(struct kobject *,struct attribute *,char *); ssize_t kobj_test_store(struct kobject *,struct attribute *,const char *,size_t); static struct attribute test_attr = { .name = "kobj_config", .mode = S_IRWXUGO, }; static struct attribute *def_attrs[] = { &test_attr, NULL, }; static struct sysfs_ops obj_test_sysops = { .show = kobj_test_show, .store = kobj_test_store, }; static struct kobj_type ktype = { .release = obj_test_release, .sysfs_ops = &obj_test_sysops, .default_attrs = def_attrs,}; void obj_test_release(struct kobject *kobject) { printk("[kobj_test: release!]\n"); } ssize_t kobj_test_show(struct kobject *kobject,struct attribute *attr,char *buf) { printk("Have show –>\n"); printk("attrname: %s.\n",attr->name); sprintf("buf,%s\n",attr->name); return strlen(attr->name) + 2; } ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size) { printk("Have store –>\n"); printk("write: %s.\n",buf); return size; } static int kset_filter(struct kset *kset,struct kobject *kobj) { printk("Filter: kobj %s.\n",kobj->name); return 1; } static 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; } static 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; } static struct kset_uevent_ops uevent_ops = { .filter = kset_filter, .name = kset_name, .uevent = kset_uevent, }; static int __init kset_test_init(void) { int ret = 0; printk("kset test init!\n"); /* 创建并注册 kset_p */ kset_p = kset_create_and_add("kset_p",&uevent_ops,NULL);

/* 添加 kset_c 到 kset_p */ kobject_set_name(&kset_c.kobj,"kset_c"); kset_c.kobj.kset = kset_p; /* 对于较新版本的内核,在注册 kset 之前,需要 * 填充 kset.kobj 的 ktype 成员,否则注册不会成功 */ kset_c.kobj.ktype = &ktype; ret = kset_register(&kset_c); if(ret) kset_unregister(kset_p); return 0; } static void __exit kset_test_exit(void) { printk("kset test exit!\n"); kset_unregister(kset_p); kset_unregister(&kset_c); } module_init(kset_test_init); module_exit(kset_test_exit);

人生,一场人喧鼓响的戏,我只是一个平凡的过客,

linux设备驱动模型之 kset原理与实例分析

相关文章:

你感兴趣的文章:

标签云: