Linux內核 簡化版kset-example.c解析
- /**********************************************
- * Author: [email protected]
- * File name: kset_sample.c
- * Description: kset example
- * Date: 2011-12-10
- *********************************************/
-
- #include <linux/kobject.h>
- #include <linux/string.h>
- #include <linux/sysfs.h>
- #include <linux/slab.h>
- #include <linux/module.h>
- #include <linux/init.h>
-
- /*
- * 將要創建的文件foo對應的kobj.
- */
- 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)
-
- /*
- * 屬性foo信息顯示函數 (涉及文件目錄foo/)
- */
- 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);
- }
-
- /*
- * 屬性foo存儲函數(涉及文件目錄foo/) (when a value is written to a file.)
- */
- 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);
- }
-
- /*
- * foo的show/store列表
- */
- static const struct sysfs_ops foo_sysfs_ops = {
- .show = foo_attr_show,
- .store = foo_attr_store,
- };
-
- /*
- * The release function for our object. This is REQUIRED by the kernel to
- * have. We free the memory held in our object here.
- */
- static void foo_release(struct kobject *kobj)
- {
- struct foo_obj *foo;
-
- foo = to_foo_obj(kobj);
- kfree(foo);
- }
-
- /*
- * 當需要從foo文件中讀取信息時,調用此函數
- */
- static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
- char *buf)
- {
- return sprintf(buf, "%d\n", foo_obj->foo);
- }
-
- /*
- * 當往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);
-
- /*
- * foo_ktype的屬性列表
- */
- static struct attribute *foo_default_attrs[] = {
- &foo_attribute.attr,
- NULL, /* need to NULL terminate the list of attributes */
- };
-
- /*
- * 定義kobj_type結構體
- * 指定sysfs_ops,release函數, 屬性列表foo_default_attrs
- */
- 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;
-
- /* allocate the memory for the whole object */
- foo = kzalloc(sizeof(*foo), GFP_KERNEL);
- if (!foo)
- return NULL;
-
- foo->kobj.kset = example_kset;
-
- /*
- * 初始化kobject數據結結構foo->lobj,
- * 即 在foo->kobj的層次組織kset中創建個名為name的文件foo/foo
- * 成功返回0
- */
- retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
- if (retval) {
- /* 減小kobj的引用計數 */
- kobject_put(&foo->kobj);
- return NULL;
- }
-
- /*
- * 發送 KOBJ_ADD / KOBJ_REMOVE 等事件
- * We are always responsible for sending the uevent that the kobject
- * was added to the system.
- */
- kobject_uevent(&foo->kobj, KOBJ_ADD);
-
- return foo;
- }
-
- static void destroy_foo_obj(struct foo_obj *foo)
- {
- /* 減小kobj的引用計數 */
- kobject_put(&foo->kobj);
- }
-
- static int __init example_init(void)
- {
- /*
- * 動態地在kernel_kobj所對應的目錄/sys/kernel/下創建一個目錄kset_example
- * 並返回kset_example對應的kset
- */
- 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("lewiyon <[email protected]>");