Linux的kobject机制
2019-07-12 20:13发布
生成海报
https://blog.csdn.net/younger_china/article/details/11180385作者:Younger Liu,
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。 sysfs文件系统下的每个目录对应于一个kobj,kset是kobj的封装,内嵌了一个kobj,其代表kset自身,ktype代表属性操作集,但由于通用性,因此把ktype单独剥离出来,kobj,kset,ktype成为了各个驱动模型最底层的关联元素,并由此形成了sys下的各种拓扑结构。1 kobject,kset,子系统层次结构内核通常用kobject结构将各个对象连接起来组成一个分层的结构体系。 一个 kset是嵌入到相同类型结构的 kobject的集合。struct kobj_type 关注的是对象的类型,而struct kset关心的是对象的集合,可认为kset是kobjects的顶层容器类。每个 kset 在内部包含自己的 kobject,并可以用多种处理kobject的方法处理kset。 kset总是在 sysfs中出现;一旦设置了 kset并把它添加到系统中,将在 sysfs 中创建一个目录;kobjects不必在 sysfs中表示, 但kset中的每一个 kobject成员都在sysfs中得到表述。 2 如何实现sysfs接口kobject 是在 sysfs虚拟文件系统后的机制。对每个在 sysfs中的目录,在内核中都会有一个 kobject与之对应。每个 kobject都输出一个或多个属性,它在 kobject 的 sysfs目录中以文件的形式出现,其中的内容由内核产生。当创建kobject 时,每个 kobject都被给定一系列默认属性。这些属性保存在 kobj_type结构中:
- struct kobj_type {
- void (*release)(struct kobject *);
- struct sysfs_ops *sysfs_ops;
- struct attribute **default_attrs;
- };
- struct attribute {
- char *name;
- struct module *owner;
- mode_t mode;
- };
sysfs 读写这些属性是由 kobj_type->sysfs_ops成员中的函数完成的:
- struct sysfs_ops {
- ssize_t (*show)(struct kobject *, struct attribute *,char *);
- ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
- const void *(*namespace)(struct kobject *, const struct attribute *);
- };
当用户空间读取一个属性时,内核会使用指向 kobject的指针(kobj)和正确的属性结构(*attr)来调用show方法,该方法将给定属性值编码进缓冲(buffer)(注意不要越界( PAGE_SIZE字节)),并返回实际数据长度。sysfs的约定要求每个属性应当包含一个可读值;若返回大量信息,需将它分为多个属性.也可对所有 kobject关联的属性使用同一个 show方法,用传递到函数的 attr指针来判断所请求的属性。有的 show方法包含对属性名字的检查。有的show方法会将属性结构嵌入另一个结构,这个结构包含需要返回属性值的信息,这时可用container_of获得上层结构的指针以返回属性值的信息。store 方法将存在缓冲(buffer)的数据( size为数据的长度,不能超过 PAGE_SIZE )解码并保存新值到属性(*attr),返回实际解码的字节数。store方法只在拥有属性的写权限时才能被调用。此时注意:接收来自用户空间的数据一定要验证其合法性。如果到数据不匹配,返回一个负的错误值。3 案例
-
- #include
- #include
- #include
- #include
- #include
- #include
-
- struct foo_obj {
- struct kobject kobj;
- int foo;
- int baz;
- int bar;
- };
-
- #define to_foo_obj(x) container_of(x, struct foo_obj, kobj)
-
- struct foo_attribute {
- struct attribute attr;
- ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);
- ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);
- };
-
- #define to_foo_attr(x) container_of(x, struct foo_attribute, attr)
-
- static ssize_t foo_attr_show(struct kobject *kobj,
- struct attribute *attr,
- char *buf)
- {
- struct foo_attribute *attribute;
- struct foo_obj *foo;
-
- attribute = to_foo_attr(attr);
- foo = to_foo_obj(kobj);
-
- if (!attribute->show)
- return -EIO;
-
- return attribute->show(foo, attribute, buf);
- }
-
- static ssize_t foo_attr_store(struct kobject *kobj,
- struct attribute *attr,
- const char *buf, size_t len)
- {
- struct foo_attribute *attribute;
- struct foo_obj *foo;
-
- attribute = to_foo_attr(attr);
- foo = to_foo_obj(kobj);
-
- if (!attribute->store)
- return -EIO;
-
- return attribute->store(foo, attribute, buf, len);
- }
-
- static const struct sysfs_ops foo_sysfs_ops = {
- .show = foo_attr_show,
- .store = foo_attr_store,
- };
-
- static void foo_release(struct kobject *kobj)
- {
- struct foo_obj *foo;
-
- foo = to_foo_obj(kobj);
- kfree(foo);
- }
-
- static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
- char *buf)
- {
- return sprintf(buf, "%d
", foo_obj->foo);
- }
-
- static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
- const char *buf, size_t count)
- {
- sscanf(buf, "%du", &foo_obj->foo);
- return count;
- }
-
- static struct foo_attribute foo_attribute =
- __ATTR(foo, 0666, foo_show, foo_store);
-
- static struct attribute *foo_default_attrs[] = {
- &foo_attribute.attr,
- NULL,
- };
-
- static struct kobj_type foo_ktype = {
- .sysfs_ops = &foo_sysfs_ops,
- .release = foo_release,
- .default_attrs = foo_default_attrs,
- };
-
- static struct kset *example_kset;
- static struct foo_obj *foo_obj;
-
- static struct foo_obj *create_foo_obj(const char *name)
- {
- struct foo_obj *foo;
- int retval;
-
-
- foo = kzalloc(sizeof(*foo), GFP_KERNEL);
- if (!foo)
- return NULL;
-
- foo->kobj.kset = example_kset;
-
-
- retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
- if (retval) {
-
- kobject_put(&foo->kobj);
- return NULL;
- }
-
-
- kobject_uevent(&foo->kobj, KOBJ_ADD);
-
- return foo;
- }
-
- static void destroy_foo_obj(struct foo_obj *foo)
- {
-
- kobject_put(&foo->kobj);
- }
-
- static int __init example_init(void)
- {
-
- example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);
- if (!example_kset)
- return -ENOMEM;
-
- foo_obj = create_foo_obj("foo");
- if (!foo_obj)
- goto foo_error;
-
- return 0;
-
- foo_error:
- return -EINVAL;
- }
-
- static void __exit example_exit(void)
- {
- destroy_foo_obj(foo_obj);
- kset_unregister(example_kset);
- }
-
- module_init(example_init);
- module_exit(example_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Younger Liu ");
4 参考资料:sysfs文件系统详解:http://blog.chinaunix.net/u1/55599/showart_1089096.htmlsysfs.h源码详析:http://blog.chinaunix.net/u1/55599/showart_1091002.htmlhttp://www.diybl.com/course/6_system/linux/Linuxjs/2008727/134055.html
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮