上一篇博客我们分析了Linux设备模型中kobject的注册和使用,在这一篇文章中,我们来看一下kset的用法。
首先我们看一个使用kset的例子,代码如下:
[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. struct my_kobject
  11. {
  12. int value;
  13. struct kobject kobj;
  14. };
  15. struct my_kobject my_kobj;
  16. void kobject_release(struct kobject *kobject);
  17. ssize_t kobject_attr_show(struct kobject *kobject, struct attribute *attr,char *buf);
  18. ssize_t kobject_attr_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count);
  19. struct attribute kobject_attr1 = {
  20. .name = "name",
  21. .mode = S_IRWXUGO,
  22. };
  23. struct attribute kobject_attr2 = {
  24. .name = "value",
  25. .mode = S_IRWXUGO,
  26. };
  27. static struct attribute *kobject_def_attrs[] = {
  28. &kobject_attr1,
  29. &kobject_attr2,
  30. NULL,
  31. };
  32. struct sysfs_ops kobject_sysfs_ops =
  33. {
  34. .show = kobject_attr_show,
  35. .store = kobject_attr_store,
  36. };
  37. struct kobj_type ktype =
  38. {
  39. .release = kobject_release,
  40. .sysfs_ops = &kobject_sysfs_ops,
  41. .default_attrs = kobject_def_attrs,
  42. };
  43. void kobject_release(struct kobject *kobject)
  44. {
  45. printk("kobject release.\n");
  46. }
  47. ssize_t kobject_attr_show(struct kobject *kobject, struct attribute *attr,char *buf)
  48. {
  49. int count = 0;
  50. struct my_kobject *my_kobj = container_of(kobject, struct my_kobject, kobj);
  51. printk("kobject attribute show.\n");
  52. if(strcmp(attr->name, "name") == 0)
  53. count = sprintf(buf, "%s\n", kobject->name);
  54. else if(strcmp(attr->name, "value") == 0)
  55. count = sprintf(buf, "%d\n", my_kobj->value);
  56. else
  57. printk("no this attribute.\n");
  58. return count;
  59. }
  60. ssize_t kobject_attr_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count)
  61. {
  62. int val;
  63. struct my_kobject *my_kobj = container_of(kobject, struct my_kobject, kobj);
  64. printk("kobject attribute store.\n");
  65. if(strcmp(attr->name, "name") == 0)
  66. printk("Can not change name.\n");
  67. else if(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. return count;
  78. }
  79. int kset_filter(struct kset *kset, struct kobject *kobj)
  80. {
  81. printk("UEVENT: filter. kobj %s.\n",kobj->name);
  82. return 1;
  83. }
  84. const char *kset_name(struct kset *kset, struct kobject *kobj)
  85. {
  86. static char buf[20];
  87. printk("UEVENT: name. kobj %s.\n",kobj->name);
  88. sprintf(buf,"%s","kset_test");
  89. return buf;
  90. }
  91. int kset_uevent(struct kset *kset, struct kobject *kobj,
  92. struct kobj_uevent_env *env)
  93. {
  94. int i = 0;
  95. printk("UEVENT: uevent. kobj %s.\n",kobj->name);
  96. while( i< env->envp_idx){
  97. printk("%s.\n",env->envp[i]);
  98. i++;
  99. }
  100. return 0;
  101. }
  102. struct kset_uevent_ops uevent_ops =
  103. {
  104. .filter = kset_filter,
  105. .name   = kset_name,
  106. .uevent = kset_uevent,
  107. };
  108. struct kset *kset_parent;
  109. struct kset kset_child;
  110. static int kset_test_init(void)
  111. {
  112. printk("kboject test init.\n");
  113. kset_parent = kset_create_and_add("kset_parent", &uevent_ops, NULL);
  114. my_kobj.kobj.kset = kset_parent;
  115. kobject_init_and_add(&my_kobj.kobj,&ktype,NULL,"kobject_test");
  116. kobject_set_name(&kset_child.kobj,"kset_child");
  117. kset_child.kobj.kset = kset_parent;
  118. kset_register(&kset_child);
  119. return 0;
  120. }
  121. static void kset_test_exit(void)
  122. {
  123. printk("kobject test exit.\n");
  124. kobject_del(&my_kobj.kobj);
  125. kset_unregister(kset_parent);
  126. kset_unregister(&kset_child);
  127. }
  128. module_init(kset_test_init);
  129. module_exit(kset_test_exit);
该模块执行结果如下图所示:
kset的注册使用kset_create_and_add函数,该函数定义如下:
[cpp] view plaincopy
  1. 820/**
  2. 821 * kset_create_and_add - create a struct kset dynamically and add it to sysfs
  3. 822 *
  4. 823 * @name: the name for the kset
  5. 824 * @uevent_ops: a struct kset_uevent_ops for the kset
  6. 825 * @parent_kobj: the parent kobject of this kset, if any.
  7. 826 *
  8. 827 * This function creates a kset structure dynamically and registers it
  9. 828 * with sysfs.  When you are finished with this structure, call
  10. 829 * kset_unregister() and the structure will be dynamically freed when it
  11. 830 * is no longer being used.
  12. 831 *
  13. 832 * If the kset was not able to be created, NULL will be returned.
  14. 833 */
  15. 834struct kset *kset_create_and_add(const char *name,
  16. 835                 const struct kset_uevent_ops *uevent_ops,
  17. 836                 struct kobject *parent_kobj)
  18. 837{
  19. 838    struct kset *kset;
  20. 839    int error;
  21. 840
  22. 841    kset = kset_create(name, uevent_ops, parent_kobj);
  23. 842    if (!kset)
  24. 843        return NULL;
  25. 844    error = kset_register(kset);
  26. 845    if (error) {
  27. 846        kfree(kset);
  28. 847        return NULL;
  29. 848    }
  30. 849    return kset;
  31. 850}
该函数首先调用kset_create创建kset,然后调用kset_register将kset注册到系统中。
先来看kset_create函数是如何创建kset的,该函数定义如下:
[cpp] view plaincopy
  1. 776/**
  2. 777 * kset_create - create a struct kset dynamically
  3. 778 *
  4. 779 * @name: the name for the kset
  5. 780 * @uevent_ops: a struct kset_uevent_ops for the kset
  6. 781 * @parent_kobj: the parent kobject of this kset, if any.
  7. 782 *
  8. 783 * This function creates a kset structure dynamically.  This structure can
  9. 784 * then be registered with the system and show up in sysfs with a call to
  10. 785 * kset_register().  When you are finished with this structure, if
  11. 786 * kset_register() has been called, call kset_unregister() and the
  12. 787 * structure will be dynamically freed when it is no longer being used.
  13. 788 *
  14. 789 * If the kset was not able to be created, NULL will be returned.
  15. 790 */
  16. 791static struct kset *kset_create(const char *name,
  17. 792                const struct kset_uevent_ops *uevent_ops,
  18. 793                struct kobject *parent_kobj)
  19. 794{
  20. 795    struct kset *kset;
  21. 796    int retval;
  22. 797
  23. 798    kset = kzalloc(sizeof(*kset), GFP_KERNEL);
  24. 799    if (!kset)
  25. 800        return NULL;
  26. 801    retval = kobject_set_name(&kset->kobj, name);
  27. 802    if (retval) {
  28. 803        kfree(kset);
  29. 804        return NULL;
  30. 805    }
  31. 806    kset->uevent_ops = uevent_ops;
  32. 807    kset->kobj.parent = parent_kobj;
  33. 808
  34. 809    /*
  35. 810     * The kobject of this kset will have a type of kset_ktype and belong to
  36. 811     * no kset itself.  That way we can properly free it when it is
  37. 812     * finished being used.
  38. 813     */
  39. 814    kset->kobj.ktype = &kset_ktype;
  40. 815    kset->kobj.kset = NULL;
  41. 816
  42. 817    return kset;
  43. 818}
798行,为kset分配空间。
801行,设置kset->kobj的名字,代表该kset的名字。
806行,设置kset->uevent_ops。
807行,设置kset->kobj.parent。
814行,将kset->kobj.ktype设置为&kset_ktype。kset_ktype我们在下面介绍。
815行,将kset->kobj.kset设置为NULL,即该kset不属于任何kset。
kset_ktype的定义如下:
[cpp] view plaincopy
  1. 771static struct kobj_type kset_ktype = {
  2. 772    .sysfs_ops  = &kobj_sysfs_ops,
  3. 773    .release = kset_release,
  4. 774};
为了分析方便,我们先来看kset_release的定义:
[cpp] view plaincopy
  1. 763static void kset_release(struct kobject *kobj)
  2. 764{
  3. 765    struct kset *kset = container_of(kobj, struct kset, kobj);
  4. 766    pr_debug("kobject: '%s' (%p): %s\n",
  5. 767         kobject_name(kobj), kobj, __func__);
  6. 768    kfree(kset);
  7. 769}
这个函数取得kset空间指针并释放内存空间。
再来看kobj_sysfs_ops的定义,注意其作用,当用户读写kset->kobj的属性文件时,就会调用kset->kobj.ktype.sysfs_ops的show和store函数,即kobj_sysfs_ops的show和store函数:
[cpp] view plaincopy
  1. 703const struct sysfs_ops kobj_sysfs_ops = {
  2. 704    .show   = kobj_attr_show,
  3. 705    .store  = kobj_attr_store,
  4. 706};
kobj_attr_show函数定义如下:
[cpp] view plaincopy
  1. 678/* default kobject attribute operations */
  2. 679static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,
  3. 680                  char *buf)
  4. 681{
  5. 682    struct kobj_attribute *kattr;
  6. 683    ssize_t ret = -EIO;
  7. 684
  8. 685    kattr = container_of(attr, struct kobj_attribute, attr);
  9. 686    if (kattr->show)
  10. 687        ret = kattr->show(kobj, kattr, buf);
  11. 688    return ret;
  12. 689}
该函数首先通过container_of宏取得包含指定attribute的kobj_attribute,然后调用kobj_attribute的show函数。
kobj_attr_store函数定义如下:
[cpp] view plaincopy
  1. 691static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,
  2. 692                   const char *buf, size_t count)
  3. 693{
  4. 694    struct kobj_attribute *kattr;
  5. 695    ssize_t ret = -EIO;
  6. 696
  7. 697    kattr = container_of(attr, struct kobj_attribute, attr);
  8. 698    if (kattr->store)
  9. 699        ret = kattr->store(kobj, kattr, buf, count);
  10. 700    return ret;
  11. 701}
该函数首先通过container_of宏取得包含指定attribute的kobj_attribute,然后调用kobj_attribute的store函数。
至此,kset_create函数我们就分析完了,回到kset_create_and_add函数中,下面我们要分析的是kset_register函数,该函数定义如下:
[cpp] view plaincopy
  1. 708/**
  2. 709 * kset_register - initialize and add a kset.
  3. 710 * @k: kset.
  4. 711 */
  5. 712int kset_register(struct kset *k)
  6. 713{
  7. 714    int err;
  8. 715
  9. 716    if (!k)
  10. 717        return -EINVAL;
  11. 718
  12. 719    kset_init(k);
  13. 720    err = kobject_add_internal(&k->kobj);
  14. 721    if (err)
  15. 722        return err;
  16. 723    kobject_uevent(&k->kobj, KOBJ_ADD);
  17. 724    return 0;
  18. 725}
719行,调用kset_init初始化kset。
720行,调用kobject_add_internal将kobject注册到系统中,在/sys下建立目录结构和属性文件。该函数我们在前一篇博客<<Linux设备模型之kobject>>已经分析过,这里不再详细分析。
723行,调用kobject_uevent函数发送KOBJ_ADD事件。
[cpp] view plaincopy
  1. 667/**
  2. 668 * kset_init - initialize a kset for use
  3. 669 * @k: kset
  4. 670 */
  5. 671void kset_init(struct kset *k)
  6. 672{
  7. 673    kobject_init_internal(&k->kobj);
  8. 674    INIT_LIST_HEAD(&k->list);
  9. 675    spin_lock_init(&k->list_lock);
  10. 676}
673行,调用kobject_init_internal初始化kset->kobj。这个函数我们在上一篇博客<<Linux设备模型之kobject>>中已经分析过了。
kobject_uevent函数定义如下:
[cpp] view plaincopy
  1. 319/**
  2. 320 * kobject_uevent - notify userspace by sending an uevent
  3. 321 *
  4. 322 * @action: action that is happening
  5. 323 * @kobj: struct kobject that the action is happening to
  6. 324 *
  7. 325 * Returns 0 if kobject_uevent() is completed with success or the
  8. 326 * corresponding error when it fails.
  9. 327 */
  10. 328int kobject_uevent(struct kobject *kobj, enum kobject_action action)
  11. 329{
  12. 330    return kobject_uevent_env(kobj, action, NULL);
  13. 331}
这个函数直接调用了kobject_uevent_env函数,定义如下:
[cpp] view plaincopy
  1. 119/**
  2. 120 * kobject_uevent_env - send an uevent with environmental data
  3. 121 *
  4. 122 * @action: action that is happening
  5. 123 * @kobj: struct kobject that the action is happening to
  6. 124 * @envp_ext: pointer to environmental data
  7. 125 *
  8. 126 * Returns 0 if kobject_uevent_env() is completed with success or the
  9. 127 * corresponding error when it fails.
  10. 128 */
  11. 129int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
  12. 130               char *envp_ext[])
  13. 131{
  14. 132    struct kobj_uevent_env *env;
  15. 133    const char *action_string = kobject_actions[action];
  16. 134    const char *devpath = NULL;
  17. 135    const char *subsystem;
  18. 136    struct kobject *top_kobj;
  19. 137    struct kset *kset;
  20. 138    const struct kset_uevent_ops *uevent_ops;
  21. 139    u64 seq;
  22. 140    int i = 0;
  23. 141    int retval = 0;
  24. 142#ifdef CONFIG_NET
  25. 143    struct uevent_sock *ue_sk;
  26. 144#endif
  27. 145
  28. 146    pr_debug("kobject: '%s' (%p): %s\n",
  29. 147         kobject_name(kobj), kobj, __func__);
  30. 148
  31. 149    /* search the kset we belong to */
  32. 150    top_kobj = kobj;
  33. 151    while (!top_kobj->kset && top_kobj->parent)
  34. 152        top_kobj = top_kobj->parent;
  35. 153
  36. 154    if (!top_kobj->kset) {
  37. 155        pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
  38. 156             "without kset!\n", kobject_name(kobj), kobj,
  39. 157             __func__);
  40. 158        return -EINVAL;
  41. 159    }
  42. 160
  43. 161    kset = top_kobj->kset;
  44. 162    uevent_ops = kset->uevent_ops;
  45. 163
  46. 164    /* skip the event, if uevent_suppress is set*/
  47. 165    if (kobj->uevent_suppress) {
  48. 166        pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
  49. 167                 "caused the event to drop!\n",
  50. 168                 kobject_name(kobj), kobj, __func__);
  51. 169        return 0;
  52. 170    }
  53. 171    /* skip the event, if the filter returns zero. */
  54. 172    if (uevent_ops && uevent_ops->filter)
  55. 173        if (!uevent_ops->filter(kset, kobj)) {
  56. 174            pr_debug("kobject: '%s' (%p): %s: filter function "
  57. 175                 "caused the event to drop!\n",
  58. 176                 kobject_name(kobj), kobj, __func__);
  59. 177            return 0;
  60. 178        }
  61. 179
  62. 180    /* originating subsystem */
  63. 181    if (uevent_ops && uevent_ops->name)
  64. 182        subsystem = uevent_ops->name(kset, kobj);
  65. 183    else
  66. 184        subsystem = kobject_name(&kset->kobj);
  67. 185    if (!subsystem) {
  68. 186        pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
  69. 187             "event to drop!\n", kobject_name(kobj), kobj,
  70. 188             __func__);
  71. 189        return 0;
  72. 190    }
  73. 191
  74. 192    /* environment buffer */
  75. 193    env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
  76. 194    if (!env)
  77. 195        return -ENOMEM;
  78. 196
  79. 197    /* complete object path */
  80. 198    devpath = kobject_get_path(kobj, GFP_KERNEL);
  81. 199    if (!devpath) {
  82. 200        retval = -ENOENT;
  83. 201        goto exit;
  84. 202    }
  85. 203
  86. 204    /* default keys */
  87. 205    retval = add_uevent_var(env, "ACTION=%s", action_string);
  88. 206    if (retval)
  89. 207        goto exit;
  90. 208    retval = add_uevent_var(env, "DEVPATH=%s", devpath);
  91. 209    if (retval)
  92. 210        goto exit;
  93. 211    retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
  94. 212    if (retval)
  95. 213        goto exit;
  96. 214
  97. 215    /* keys passed in from the caller */
  98. 216    if (envp_ext) {
  99. 217        for (i = 0; envp_ext[i]; i++) {
  100. 218            retval = add_uevent_var(env, "%s", envp_ext[i]);
  101. 219            if (retval)
  102. 220                goto exit;
  103. 221        }
  104. 222    }
  105. 223
  106. 224    /* let the kset specific function add its stuff */
  107. 225    if (uevent_ops && uevent_ops->uevent) {
  108. 226        retval = uevent_ops->uevent(kset, kobj, env);
  109. 227        if (retval) {
  110. 228            pr_debug("kobject: '%s' (%p): %s: uevent() returned "
  111. 229                 "%d\n", kobject_name(kobj), kobj,
  112. 230                 __func__, retval);
  113. 231            goto exit;
  114. 232        }
  115. 233    }
  116. 234
  117. 235    /*
  118. 236     * Mark "add" and "remove" events in the object to ensure proper
  119. 237     * events to userspace during automatic cleanup. If the object did
  120. 238     * send an "add" event, "remove" will automatically generated by
  121. 239     * the core, if not already done by the caller.
  122. 240     */
  123. 241    if (action == KOBJ_ADD)
  124. 242        kobj->state_add_uevent_sent = 1;
  125. 243    else if (action == KOBJ_REMOVE)
  126. 244        kobj->state_remove_uevent_sent = 1;
  127. 245
  128. 246    /* we will send an event, so request a new sequence number */
  129. 247    spin_lock(&sequence_lock);
  130. 248    seq = ++uevent_seqnum;
  131. 249    spin_unlock(&sequence_lock);
  132. 250    retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
  133. 251    if (retval)
  134. 252        goto exit;
  135. 253
  136. 254#if defined(CONFIG_NET)
  137. 255    /* send netlink message */
  138. 256    mutex_lock(&uevent_sock_mutex);
  139. 257    list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  140. 258        struct sock *uevent_sock = ue_sk->sk;
  141. 259        struct sk_buff *skb;
  142. 260        size_t len;
  143. 261
  144. 262        /* allocate message with the maximum possible size */
  145. 263        len = strlen(action_string) + strlen(devpath) + 2;
  146. 264        skb = alloc_skb(len + env->buflen, GFP_KERNEL);
  147. 265        if (skb) {
  148. 266            char *scratch;
  149. 267
  150. 268            /* add header */
  151. 269            scratch = skb_put(skb, len);
  152. 270            sprintf(scratch, "%s@%s", action_string, devpath);
  153. 271
  154. 272            /* copy keys to our continuous event payload buffer */
  155. 273            for (i = 0; i < env->envp_idx; i++) {
  156. 274                len = strlen(env->envp[i]) + 1;
  157. 275                scratch = skb_put(skb, len);
  158. 276                strcpy(scratch, env->envp[i]);
  159. 277            }
  160. 278
  161. 279            NETLINK_CB(skb).dst_group = 1;
  162. 280            retval = netlink_broadcast_filtered(uevent_sock, skb,
  163. 281                                0, 1, GFP_KERNEL,
  164. 282                                kobj_bcast_filter,
  165. 283                                kobj);
  166. 284            /* ENOBUFS should be handled in userspace */
  167. 285            if (retval == -ENOBUFS)
  168. 286                retval = 0;
  169. 287        } else
  170. 288            retval = -ENOMEM;
  171. 289    }
  172. 290    mutex_unlock(&uevent_sock_mutex);
  173. 291#endif
  174. 292
  175. 293    /* call uevent_helper, usually only enabled during early boot */
  176. 294    if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
  177. 295        char *argv [3];
  178. 296
  179. 297        argv [0] = uevent_helper;
  180. 298        argv [1] = (char *)subsystem;
  181. 299        argv [2] = NULL;
  182. 300        retval = add_uevent_var(env, "HOME=/");
  183. 301        if (retval)
  184. 302            goto exit;
  185. 303        retval = add_uevent_var(env,
  186. 304                    "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
  187. 305        if (retval)
  188. 306            goto exit;
  189. 307
  190. 308        retval = call_usermodehelper(argv[0], argv,
  191. 309                         env->envp, UMH_WAIT_EXEC);
  192. 310    }
  193. 311
  194. 312exit:
  195. 313    kfree(devpath);
  196. 314    kfree(env);
  197. 315    return retval;
  198. 316}
133由参数action取得代表事件类型的字符串。kobject_actions定义如下:
[cpp] view plaincopy
  1. 40/*
  2. 41 * The actions here must match the index to the string array
  3. 42 * in lib/kobject_uevent.c
  4. 43 *
  5. 44 * Do not add new actions here without checking with the driver-core
  6. 45 * maintainers. Action strings are not meant to express subsystem
  7. 46 * or device specific properties. In most cases you want to send a
  8. 47 * kobject_uevent_env(kobj, KOBJ_CHANGE, env) with additional event
  9. 48 * specific variables added to the event environment.
  10. 49 */
  11. 50enum kobject_action {
  12. 51    KOBJ_ADD,
  13. 52    KOBJ_REMOVE,
  14. 53    KOBJ_CHANGE,
  15. 54    KOBJ_MOVE,
  16. 55    KOBJ_ONLINE,
  17. 56    KOBJ_OFFLINE,
  18. 57    KOBJ_MAX
  19. 58};
  20. 42/* the strings here must match the enum in include/linux/kobject.h */
  21. 43static const char *kobject_actions[] = {
  22. 44    [KOBJ_ADD] =        "add",
  23. 45    [KOBJ_REMOVE] =     "remove",
  24. 46    [KOBJ_CHANGE] =     "change",
  25. 47    [KOBJ_MOVE] =       "move",
  26. 48    [KOBJ_ONLINE] =     "online",
  27. 49    [KOBJ_OFFLINE] =    "offline",
  28. 50};
149 - 162行,因为只有kset才包含处理uevent的函数,即kset.uevent_ops,所以这里查找kobj所属的kset,如果kobj->kset不存在,就沿着kobj->parent向上查找,直到找到一个不为空的kset为止。如果确实没有找到kset,则退出。
165 - 170行,如果kobj->uevent_suppress的值为1,表示禁止发出uevent事件,退出。
172 - 178行,如果uevent_ops不为空,并且实现了uevent_ops->filter,则执行uevent_ops->filter,如果uevent_ops->filter返回值为0,表示这个uevent被过滤了,退出。
181 - 190行,如果uevent_ops不为空,并且实现了uevent_ops->name,则通过uevent_ops->name获得子系统名,如果uevent_ops为空,或者没有实现uevent_ops->name,则以kset->kobj的名字作为子系统名。
193行,创建kobj_uevent_env结构体变量env,用来保存环境变量。
198行,通过调用kobject_get_path函数取得kobj在/sys系统中的路径,保存在devpath变量中。
205 - 213行,通过调用add_uevent_var函数将事件名,kobj路径和子系统名加入到环境变量env中。
216 - 222行,如果有通过参数传递的环境变量,也调用add_uevent_var函数加入到环境变量env中。
225 - 233行,如果uevent_ops不为空,并且实现了uevent_ops->uevent函数,则调用uevent_ops->uevent。
241 - 244行,如果要发送的事件是KOBJ_ADD或KOBJ_REMOVE,则相应将kobj->state_add_uevent_sent或kobj->state_remove_uevent_sent置为1。
247 - 252行,将发送事件序列数加1,添加到环境变量env中。
254 - 291行,条件编译部分我们不分析。
294行,先来看uevent_helper的定义:
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
#define UEVENT_HELPER_PATH_LEN      256
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
所以uevent_helper就是"/sbin/hotplug"。
300 - 306行,将HOME和PATH加入环境变量env中。
308 - 309行,执行用户空间的/sbin/hotplug程序,传递环境变量为env。
至此, kobject_uevent_env -> kobject_uevent -> kset_register -> kset_create_and_add函数就分析完了,kset被创建和注册到系统中。

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

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

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

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

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

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

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

  4. Linux设备模型分析之kobject

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

  5. linux设备模型——总线,驱动,设备间的关系

    设备模型之kobject,kset及其关系 关于linux设备模型kobject,kset,ktype 设备驱动基础0:设备模型之kobject,kset及其关系 设备模型之总线,驱动,设备 Linu ...

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

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

  7. Linux设备模型:kset, kobj, ktype

    参照本站转载LWN文章:<kobject/kset/ktype documentation and example code updated> 本文转自:LoyenWang 目录 1. 概 ...

  8. Linux设备模型剖析系列一(基本概念、kobject、kset、kobj_type)

    CSDN链接: Linux设备模型剖析系列一(基本概念.kobject.kset.kobj_type) Linux设备模型剖析系列之二(uevent.sysfs) Linux设备模型剖析系列之三(de ...

  9. Linux设备模型 kobject kset

    http://www.wowotech.net/device_model/13.html 1. 前言 在"Linux内核的整体架构"中,蜗蜗有提到,由于Linux支持世界上几乎所有 ...

最新文章

  1. QEMU — VirtIO 的网络实现
  2. 聚焦和增强卷积神经网络
  3. 深入理解Lustre文件系统-第1篇 前言
  4. Nagios远程监控软件的安装与配置详解
  5. 解决 Windows 和 Ubuntu 时间不一致的问题--转载
  6. 细说 Vue.js 3.2 关于响应式部分的优化
  7. 基于easyui开发Web版Activiti流程定制器详解(六)——Draw2d的扩展(一)
  8. 一般使用作为微型计算机必备,远程教育统考复习之计算机应用基础单选模拟复习题(一)...
  9. Matlab多种群遗传算法
  10. 【Tensorflow】基于卷积神经网络实现车牌的识别
  11. 线性约束最优化问题的Frank-Wolfe方法
  12. Kubernetes 学习笔记(一)--- 基本概念及利用kubeadm部署K8S
  13. 计算机无法还原,win7系统不能还原如何解决_win7电脑无法还原系统怎么办-win7之家...
  14. 像玩游戏一样做游戏 | Google Play 开发者故事
  15. Pathon基础篇数据类型之——数值、字符串与列表内容
  16. 沧海桑田:Linux 系统启动的演进模型与发展变化
  17. javac不是内部或外部命令,也不是可运行的程序 或批处理文件的细节问题(window10)
  18. RN-路由---基础
  19. SQL48 将所有获取奖金的员工当前的薪水增加10%
  20. yui2 datatable转换至yui3

热门文章

  1. MayaDay1:各种复制
  2. redis主从数据丢失解决方案
  3. Windows MSDT RCE(CVE-2022-30190)复现
  4. 工业用微型计算机资料,《工业用微型计算机》串讲资料(一).doc
  5. 乐学python编程做个游戏很简单_乐学Python编程-做个游戏很简单
  6. 获取手机数据信号强度dbm数值
  7. 共建全场景智慧广州,加速人工智能和数字经济产业发展
  8. 2024届,该怎么找工作?
  9. 【有利可图网】PS教程:PS设计打造海报中常见的中文特效艺术字
  10. signature=ac75cb7977a45c0f7d8a73dca59a4c27,Mac版闪退