一、kobject应用举例
Linux设备模型最基本的组成元素是kobject,我们先来看一个kobject的应用例子,该程序在Ubuntu 10.10, 2.6.32-38-generic-pae内核上调试通过。

[cpp] view plaincopy

  1. #include <linux/device.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>
  5. #include <linux/string.h>
  6. #include <linux/sysfs.h>
  7. #include <linux/stat.h>
  8. MODULE_AUTHOR("haoyu");
  9. MODULE_LICENSE("Dual BSD/GPL");
  10. structmy_kobject
  11. {
  12. intvalue;
  13. structkobject kobj;
  14. };
  15. structmy_kobject my_kobj;
  16. voidkobject_release(structkobject *kobject);
  17. ssize_t kobject_attr_show(structkobject *kobject,structattribute *attr,char*buf);
  18. ssize_t kobject_attr_store(structkobject *kobject,structattribute *attr,constchar*buf,size_tcount);
  19. structattribute kobject_attr1 = {
  20. .name = "name",
  21. .mode = S_IRWXUGO,
  22. };
  23. structattribute kobject_attr2 = {
  24. .name = "value",
  25. .mode = S_IRWXUGO,
  26. };
  27. staticstructattribute *kobject_def_attrs[] = {
  28. &kobject_attr1,
  29. &kobject_attr2,
  30. NULL,
  31. };
  32. structsysfs_ops kobject_sysfs_ops =
  33. {
  34. .show = kobject_attr_show,
  35. .store = kobject_attr_store,
  36. };
  37. structkobj_type ktype =
  38. {
  39. .release = kobject_release,
  40. .sysfs_ops = &kobject_sysfs_ops,
  41. .default_attrs = kobject_def_attrs,
  42. };
  43. voidkobject_release(structkobject *kobject)
  44. {
  45. printk("kobject release.\n");
  46. }
  47. ssize_t kobject_attr_show(structkobject *kobject,structattribute *attr,char*buf)
  48. {
  49. intcount = 0;
  50. structmy_kobject *my_kobj = container_of(kobject,structmy_kobject, kobj);
  51. printk("kobject attribute show.\n");
  52. if(strcmp(attr->name,"name") == 0)
  53. count = sprintf(buf, "%s\n", kobject->name);
  54. elseif(strcmp(attr->name,"value") == 0)
  55. count = sprintf(buf, "%d\n", my_kobj->value);
  56. else
  57. printk("no this attribute.\n");
  58. returncount;
  59. }
  60. ssize_t kobject_attr_store(structkobject *kobject,structattribute *attr,constchar*buf,size_tcount)
  61. {
  62. intval;
  63. structmy_kobject *my_kobj = container_of(kobject,structmy_kobject, kobj);
  64. printk("kobject attribute store.\n");
  65. if(strcmp(attr->name,"name") == 0)
  66. printk("Can not change name.\n");
  67. elseif(strcmp(attr->name,"value") == 0)
  68. {
  69. val = buf[0] - '0';
  70. if(val == 0 || val == 1)
  71. my_kobj->value = val;
  72. else
  73. printk("value is '0' or '1'\n");
  74. }
  75. else
  76. printk("no this attribute.\n");
  77. returncount;
  78. }
  79. staticintkobject_test_init(void)
  80. {
  81. printk("kboject test init.\n");
  82. kobject_init_and_add(&my_kobj.kobj,&ktype,NULL,"kobject_test");
  83. return0;
  84. }
  85. staticvoidkobject_test_exit(void)
  86. {
  87. printk("kobject test exit.\n");
  88. kobject_del(&my_kobj.kobj);
  89. }
  90. module_init(kobject_test_init);
  91. module_exit(kobject_test_exit);

该模块执行过程如下图所示:
 

二、相关数据结构:
kobject是Linux设备模型中最基本的数据结构,代表设备模式的一个基本对象。
kobj_type是kobject的类型,包括kobject的属性以及属性的操作接口,不同的kobject可以具有相同的kobj_type。
kset是几个kobject的集合,这些kobject可以具有相同的kobj_type,也可以具有不同的kobj_type。

三、kobject注册和注销过程分析
kobject的注册是通过调用kobject_init_and_add函数,该函数定义如下:

先来看kobject_init,该函数定义如下:

kobject_init_internal函数定义如下:

至此,kobject_init函数就分析完了,我们返回到kobject_init_and_add函数,下面该分析kobject_add_varg函数了:


然后,调用create_dir(kobj)在/sys目录下建立kobject相关目录结构。
kobj_kset_join函数定义如下:


sysfs_create_dir函数定义如下:

下面来看populate_dir函数,其定义如下:

至此,kobject的注册过程我们就分析完了。
kobject的注销过程是调用kobject_del函数,该函数定义如下:

[cpp] view plaincopy

  1. /**
  2. * kobject_del - unlink kobject from hierarchy.
  3. * @kobj: object.
  4. */
  5. voidkobject_del(structkobject *kobj)
  6. {
  7. if(!kobj)
  8. return;
  9. sysfs_remove_dir(kobj);
  10. kobj->state_in_sysfs = 0;
  11. kobj_kset_leave(kobj);
  12. kobject_put(kobj->parent);
  13. kobj->parent = NULL;
  14. }
这里需要注意的是,只要把目录删除,目录下的属性文件自动就删除了。
[cpp] view plaincopy

  1. /*
  2. * populate_dir - populate directory with attributes.
  3. * @kobj: object we're working on.
  4. *
  5. * Most subsystems have a set of default attributes that are associated
  6. * with an object that registers with them.  This is a helper called during
  7. * object registration that loops through the default attributes of the
  8. * subsystem and creates attributes files for them in sysfs.
  9. */
  10. staticintpopulate_dir(structkobject *kobj)
  11. {
  12. structkobj_type *t = get_ktype(kobj);
  13. structattribute *attr;
  14. interror = 0;
  15. inti;
  16. if(t && t->default_attrs) {
  17. for(i = 0; (attr = t->default_attrs[i]) != NULL; i++) {
  18. error = sysfs_create_file(kobj, attr);
  19. if(error)
  20. break;
  21. }
  22. }
  23. returnerror;
  24. }
该函数循环遍历kobject的所有属性,并调用sysfs_create_file函数在/sys系统对应目录下建立属性文件。
[cpp] view plaincopy

  1. /**
  2. *      sysfs_create_dir - create a directory for an object.
  3. *      @kobj:         object we're creating directory for.
  4. */
  5. intsysfs_create_dir(structkobject * kobj)
  6. {
  7. enumkobj_ns_type type;
  8. structsysfs_dirent *parent_sd, *sd;
  9. constvoid*ns = NULL;
  10. interror = 0;
  11. BUG_ON(!kobj);
  12. if(kobj->parent)
  13. parent_sd = kobj->parent->sd;
  14. else
  15. parent_sd = &sysfs_root;
  16. if(sysfs_ns_type(parent_sd))
  17. ns = kobj->ktype->namespace(kobj);
  18. type = sysfs_read_ns_type(kobj);
  19. error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd);
  20. if(!error)
  21. kobj->sd = sd;
  22. returnerror;
  23. }
这里主要是通过调用create_dir函数建立kobject对应的目录。这个函数我们就不继续向下跟踪了。
[cpp] view plaincopy

  1. staticintcreate_dir(structkobject *kobj)
  2. {
  3. interror = 0;
  4. if(kobject_name(kobj)) {
  5. error = sysfs_create_dir(kobj);
  6. if(!error) {
  7. error = populate_dir(kobj);
  8. if(error)
  9. sysfs_remove_dir(kobj);
  10. }
  11. }
  12. returnerror;
  13. }
首先调用sysfs_create_dir在/sys下建立目录,然后再调用populate_dir在新建目录下生成属性文件。
[cpp] view plaincopy

  1. /* add the kobject to its kset's list */
  2. staticvoidkobj_kset_join(structkobject *kobj)
  3. {
  4. if(!kobj->kset)
  5. return;
  6. kset_get(kobj->kset);
  7. spin_lock(&kobj->kset->list_lock);
  8. list_add_tail(&kobj->entry, &kobj->kset->list);
  9. spin_unlock(&kobj->kset->list_lock);
  10. }
create_dir函数定义如下:
[cpp] view plaincopy

  1. staticintkobject_add_internal(structkobject *kobj)
  2. {
  3. interror = 0;
  4. structkobject *parent;
  5. if(!kobj)
  6. return-ENOENT;
  7. if(!kobj->name || !kobj->name[0]) {
  8. WARN(1, "kobject: (%p): attempted to be registered with empty "
  9. "name!\n", kobj);
  10. return-EINVAL;
  11. }
  12. parent = kobject_get(kobj->parent);
  13. /* join kset if set, use it as parent if we do not already have one */
  14. if(kobj->kset) {
  15. if(!parent)
  16. parent = kobject_get(&kobj->kset->kobj);
  17. kobj_kset_join(kobj);
  18. kobj->parent = parent;
  19. }
  20. pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
  21. kobject_name(kobj), kobj, __func__,
  22. parent ? kobject_name(parent) : "<NULL>",
  23. kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
  24. error = create_dir(kobj);
  25. if(error) {
  26. kobj_kset_leave(kobj);
  27. kobject_put(parent);
  28. kobj->parent = NULL;
  29. /* be noisy on error issues */
  30. if(error == -EEXIST)
  31. printk(KERN_ERR "%s failed for %s with "
  32. "-EEXIST, don't try to register things with "
  33. "the same name in the same directory.\n",
  34. __func__, kobject_name(kobj));
  35. else
  36. printk(KERN_ERR "%s failed for %s (%d)\n",
  37. __func__, kobject_name(kobj), error);
  38. dump_stack();
  39. else
  40. kobj->state_in_sysfs = 1;
  41. returnerror;
  42. }
首先确保kobj->name已经被赋值,即kobject必须有名字。如果指定了kobj->kset,则调用kobj_kset_join将kobj加入到kobj->kset中。同时,如果kobj->parent仍为NULL,则将kobj->parent设置为kobj->kset->kobj。
[cpp] view plaincopy

  1. staticintkobject_add_varg(structkobject *kobj,structkobject *parent,
  2. constchar*fmt,va_listvargs)
  3. {
  4. intretval;
  5. retval = kobject_set_name_vargs(kobj, fmt, vargs);
  6. if(retval) {
  7. printk(KERN_ERR "kobject: can not set name properly!\n");
  8. returnretval;
  9. }
  10. kobj->parent = parent;
  11. returnkobject_add_internal(kobj);
  12. }
首先调用kobject_set_name_vargs设置kob->name。然后初始化kobj->parent为parent参数指定的kobject。最后,调用kobject_add_internal将kobject注册到系统中,该函数定义如下:
[cpp] view plaincopy

  1. staticvoidkobject_init_internal(structkobject *kobj)
  2. {
  3. if(!kobj)
  4. return;
  5. kref_init(&kobj->kref);
  6. INIT_LIST_HEAD(&kobj->entry);
  7. kobj->state_in_sysfs = 0;
  8. kobj->state_add_uevent_sent = 0;
  9. kobj->state_remove_uevent_sent = 0;
  10. kobj->state_initialized = 1;
  11. }
首先初始化kobj->kref,实际上kobj->kref就是一个原子变量(atomic_t)。接着初始化链表项kobj->entry,并设置其他kobject成员。
[cpp] view plaincopy

  1. /**
  2. * kobject_init - initialize a kobject structure
  3. * @kobj: pointer to the kobject to initialize
  4. * @ktype: pointer to the ktype for this kobject.
  5. *
  6. * This function will properly initialize a kobject such that it can then
  7. * be passed to the kobject_add() call.
  8. *
  9. * After this function is called, the kobject MUST be cleaned up by a call
  10. * to kobject_put(), not by a call to kfree directly to ensure that all of
  11. * the memory is cleaned up properly.
  12. */
  13. voidkobject_init(structkobject *kobj,structkobj_type *ktype)
  14. {
  15. char*err_str;
  16. if(!kobj) {
  17. err_str = "invalid kobject pointer!";
  18. gotoerror;
  19. }
  20. if(!ktype) {
  21. err_str = "must have a ktype to be initialized properly!\n";
  22. gotoerror;
  23. }
  24. if(kobj->state_initialized) {
  25. /* do not error out as sometimes we can recover */
  26. printk(KERN_ERR "kobject (%p): tried to init an initialized "
  27. "object, something is seriously wrong.\n", kobj);
  28. dump_stack();
  29. }
  30. kobject_init_internal(kobj);
  31. kobj->ktype = ktype;
  32. return;
  33. error:
  34. printk(KERN_ERR "kobject (%p): %s\n", kobj, err_str);
  35. dump_stack();
  36. }
该函数首先确保kobj和ktype都存在,否则直接退出。如果该kobj进行过初始化,则打印警告信息。然后调用kobject_init_internal真正开始初始化kobj,最后把kobj->ktype设置为ktype。
[cpp] view plaincopy

  1. /**
  2. * kobject_init_and_add - initialize a kobject structure and add it to the kobject hierarchy
  3. * @kobj: pointer to the kobject to initialize
  4. * @ktype: pointer to the ktype for this kobject.
  5. * @parent: pointer to the parent of this kobject.
  6. * @fmt: the name of the kobject.
  7. *
  8. * This function combines the call to kobject_init() and
  9. * kobject_add().  The same type of error handling after a call to
  10. * kobject_add() and kobject lifetime rules are the same here.
  11. */
  12. intkobject_init_and_add(structkobject *kobj,structkobj_type *ktype,
  13. structkobject *parent,constchar*fmt, ...)
  14. {
  15. va_listargs;
  16. intretval;
  17. kobject_init(kobj, ktype);
  18. va_start(args, fmt);
  19. retval = kobject_add_varg(kobj, parent, fmt, args);
  20. va_end(args);
  21. returnretval;
  22. }
这个函数分为两部分,首先调用kobject_init函数对kobject对象进行基本的初始化。然后,调用kobject_add_varg函数将kobject注册到系统中。va_start和va_end是处理可变参数的固定语法。
[cpp] view plaincopy

  1. structkobject {
  2. constchar*name;
  3. structlist_head       entry;
  4. structkobject         *parent;
  5. structkset            *kset;
  6. structkobj_type       *ktype;
  7. structsysfs_dirent    *sd;
  8. structkref            kref;
  9. unsigned intstate_initialized:1;
  10. unsigned intstate_in_sysfs:1;
  11. unsigned intstate_add_uevent_sent:1;
  12. unsigned intstate_remove_uevent_sent:1;
  13. unsigned intuevent_suppress:1;
  14. };
  15. /**
  16. * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
  17. *
  18. * A kset defines a group of kobjects.  They can be individually
  19. * different "types" but overall these kobjects all want to be grouped
  20. * together and operated on in the same manner.  ksets are used to
  21. * define the attribute callbacks and other common events that happen to
  22. * a kobject.
  23. *
  24. * @list: the list of all kobjects for this kset
  25. * @list_lock: a lock for iterating over the kobjects
  26. * @kobj: the embedded kobject for this kset (recursion, isn't it fun...)
  27. * @uevent_ops: the set of uevent operations for this kset.  These are
  28. * called whenever a kobject has something happen to it so that the kset
  29. * can add new environment variables, or filter out the uevents if so
  30. * desired.
  31. */
  32. structkset {
  33. structlist_head list;
  34. spinlock_t list_lock;
  35. structkobject kobj;
  36. conststructkset_uevent_ops *uevent_ops;
  37. };
  38. structkset_uevent_ops {
  39. int(*constfilter)(structkset *kset,structkobject *kobj);
  40. constchar*(*constname)(structkset *kset,structkobject *kobj);
  41. int(*constuevent)(structkset *kset,structkobject *kobj,
  42. structkobj_uevent_env *env);
  43. };
  44. structkobj_type {
  45. void(*release)(structkobject *kobj);
  46. conststructsysfs_ops *sysfs_ops;
  47. structattribute **default_attrs;
  48. conststructkobj_ns_type_operations *(*child_ns_type)(structkobject *kobj);
  49. constvoid*(*namespace)(structkobject *kobj);
  50. };
  51. structsysfs_ops {
  52. ssize_t (*show)(structkobject *,structattribute *,char*);
  53. ssize_t (*store)(structkobject *,structattribute *,constchar*,size_t);
  54. };
  55. structattribute {
  56. constchar*name;
  57. mode_t                 mode;
  58. #ifdef CONFIG_DEBUG_LOCK_ALLOC
  59. structlock_class_key  *key;
  60. structlock_class_key  skey;
  61. #endif
  62. };
  63. /*
  64. * Callbacks so sysfs can determine namespaces
  65. *   @current_ns: return calling task's namespace
  66. *   @netlink_ns: return namespace to which a sock belongs (right?)
  67. *   @initial_ns: return the initial namespace (i.e. init_net_ns)
  68. */
  69. structkobj_ns_type_operations {
  70. enumkobj_ns_type type;
  71. constvoid*(*current_ns)(void);
  72. constvoid*(*netlink_ns)(structsock *sk);
  73. constvoid*(*initial_ns)(void);
  74. };
  75. structkref {
  76. atomic_t refcount;
  77. };

Linux设备模型分析之kobject相关推荐

  1. Linux设备模型分析之kobject(基于3.10.1内核)

    一.kobject结构定义 kobject是Linux设备模型的最底层数据结构,它代表一个内核对象. kobject结构体定义在include/linux/kobject.h文件中: [cpp] vi ...

  2. Linux设备模型分析之kset

    上一篇博客我们分析了Linux设备模型中kobject的注册和使用,在这一篇文章中,我们来看一下kset的用法. 首先我们看一个使用kset的例子,代码如下: [cpp] view plaincopy ...

  3. Linux 设备模型之 (kobject、kset 和 Subsystem)(二)

    1.kobject 结构 在Linux内核里,kobject是组成Linux设备模型的基础,一个kobject对应sysfs里的一个目录.从面向对象的角度来说,kobject可以看作是所有设备对象的基 ...

  4. linux kset subsystem 3.10内核,Linux设备模型分析之kset(基于3.10.1内核)

    作者:刘昊昱 内核版本:3.10.1 一.kset结构定义 kset结构体定义在include/linux/kobject.h文件中,其内容如下: 142/** 143 * struct kset - ...

  5. Linux设备模型分析之kset(基于3.10.1内核)

    一.kset结构定义 kset结构体定义在include/linux/kobject.h文件中,其内容如下: [cpp] view plaincopy 142/** 143 * struct kset ...

  6. linux设备模型:bus概念及pci_bus分析

    上一篇<<linux设备模型:kset及设备驱动抽象类(class)分析>>中分析了kset容器.class设备驱动抽象框架.class_kset用于类(class)的热插拔事 ...

  7. linux设备模型:devtmpfs虚拟文件系统分析

    devtmpfs是一个设备文件系统,它将其所有文件保存在虚拟内存中. devtmpfs中的所有内容都是临时的,因为不会在您的硬盘驱动器上创建任何文件.如果卸载devtmpfs实例,其中存储的所有内容都 ...

  8. linux设备模型:pci驱动程序注册过程

    一个具有正常探测功能的pci驱动程序应具有基本的pci_driver结构实现,如: static struct pci_driver driver_ops = {.name = "drive ...

  9. linux设备模型之kset/kobj/ktype分析

    1. 概述 今天来聊一下Linux设备模型的基石:kset/kobject/ktype. sysfs文件系统提供了一种用户与内核数据结构进行交互的方式,可以通过mount -t sysfs sysfs ...

最新文章

  1. Memcache知识点梳理
  2. C\S B\S 结果,其实就是这个样子的。
  3. 在HTML5 localStorage中存储对象
  4. mybaits十七:使用foreach标签
  5. pyhanlp 停用词与用户自定义词典
  6. Error querying database.Cause:java.sql.SQLSyntaxErrorException:ORA-00911:invalid character
  7. m6000路由器产品介绍与基本操作_交换机与路由器的区别及光模块搭配方案_光模块吧...
  8. python 模块学习--Numpy
  9. Python问题记录
  10. 音响上的英文是什么意思_鞋盒上的字母后缀 是什么意思?(上)
  11. ubuntu命令和配置文件 修改IP
  12. C#设计模式系列 8 ----Builder 生成器模式之--发工资了,带老婆到 岗顶百脑汇配置电脑...
  13. Nginx SSL 性能调优
  14. C++ const型成员函数与 non-const型成员函数 (二)
  15. arm体系结构与编程_ARM体系结构基础(1)
  16. 一个周末掌握IT前沿技术之node.js篇一:Node.js与javascript
  17. 【转】数字会议系统功能之解析
  18. pyton 内置模块
  19. windows server2012R2 apache+mod_wsgi+django
  20. java sub函数,请问Sub子过程与Function函数过程有什么区别?

热门文章

  1. 0基础趣学SEO,引爆流量,让客户主动找上门的躺赚神技
  2. 超全的iOS面试题汇总
  3. 服务器RAID配置全程
  4. ubuntu 16.04 内存清理方法总结
  5. 微信公众号获取关注页面链接
  6. java点击按钮隐藏图片6_原生JS实现隐藏显示图片 JS实现点击切换图片效果
  7. 互联网公司为何杀死中年人?三年醇,五年陈,十年滚!
  8. python-机器学习-手写数字识别
  9. 测试语文水平的软件,语文试卷质量分析
  10. 北京摇号系统服务器,支付宝“城市服务”平台可查询北京小客车摇号结果