Linux設備模型分析之kset

作者:劉昊昱 

博客:http://blog.csdn.net/liuhaoyutz

內核版本:2.6.36

 
上一篇博客我們分析了Linux設備模型中kobject的註冊和使用,在這一篇文章中,我們來看一下kset的用法。
首先我們看一個使用kset的例子,代碼如下:
  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.    
  9. MODULE_AUTHOR("haoyu");  
  10. MODULE_LICENSE("Dual BSD/GPL");  
  11.    
  12. struct my_kobject  
  13. {  
  14.     int value;  
  15.     struct kobject kobj;  
  16. };  
  17.       
  18. struct my_kobject my_kobj;  
  19.    
  20. void kobject_release(struct kobject *kobject);  
  21. ssize_t kobject_attr_show(struct kobject *kobject, struct attribute *attr,char *buf);  
  22. ssize_t kobject_attr_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count);  
  23.    
  24. struct attribute kobject_attr1 = {  
  25.     .name = "name",  
  26.     .mode = S_IRWXUGO,  
  27. };  
  28.    
  29. struct attribute kobject_attr2 = {  
  30.     .name = "value",  
  31.     .mode = S_IRWXUGO,  
  32. };  
  33.    
  34. static struct attribute *kobject_def_attrs[] = {  
  35.     &kobject_attr1,  
  36.     &kobject_attr2,  
  37.     NULL,  
  38. };  
  39.    
  40. struct sysfs_ops kobject_sysfs_ops =  
  41. {  
  42.     .show = kobject_attr_show,  
  43.     .store = kobject_attr_store,  
  44. };  
  45.    
  46. struct kobj_type ktype =  
  47. {  
  48.     .release = kobject_release,  
  49.     .sysfs_ops = &kobject_sysfs_ops,  
  50.     .default_attrs = kobject_def_attrs,  
  51. };  
  52.    
  53. void kobject_release(struct kobject *kobject)  
  54. {  
  55.     printk("kobject release.\n");  
  56. }  
  57.    
  58. ssize_t kobject_attr_show(struct kobject *kobject, struct attribute *attr,char *buf)  
  59. {  
  60.     int count = 0;  
  61.     struct my_kobject *my_kobj = container_of(kobject, struct my_kobject, kobj);  
  62.     printk("kobject attribute show.\n");  
  63.     if(strcmp(attr->name, "name") == 0)  
  64.         count = sprintf(buf, "%s\n", kobject->name);  
  65.     else if(strcmp(attr->name, "value") == 0)  
  66.         count = sprintf(buf, "%d\n", my_kobj->value);  
  67.     else  
  68.         printk("no this attribute.\n");  
  69.       
  70.     return count;  
  71. }  
  72.    
  73. ssize_t kobject_attr_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count)  
  74. {  
  75.     int val;  
  76.     struct my_kobject *my_kobj = container_of(kobject, struct my_kobject, kobj);  
  77.     printk("kobject attribute store.\n");  
  78.     if(strcmp(attr->name, "name") == 0)  
  79.         printk("Can not change name.\n");  
  80.     else if(strcmp(attr->name, "value") == 0)  
  81.     {  
  82.         val = buf[0] - '0';  
  83.         if(val == 0 || val == 1)  
  84.             my_kobj->value = val;  
  85.         else  
  86.             printk("value is '0' or '1'\n");  
  87.     }  
  88.     else  
  89.         printk("no this attribute.\n");  
  90.           
  91.     return count;  
  92. }  
  93.    
  94. int kset_filter(struct kset *kset, struct kobject *kobj)  
  95. {  
  96.     printk("UEVENT: filter. kobj %s.\n",kobj->name);  
  97.     return 1;  
  98. }  
  99.    
  100. const char *kset_name(struct kset *kset, struct kobject *kobj)  
  101. {  
  102.     static char buf[20];  
  103.     printk("UEVENT: name. kobj %s.\n",kobj->name);  
  104.     sprintf(buf,"%s","kset_test");  
  105.     return buf;  
  106. }  
  107.    
  108. int kset_uevent(struct kset *kset, struct kobject *kobj,  
  109.                 struct kobj_uevent_env *env)  
  110. {  
  111.     int i = 0;  
  112.     printk("UEVENT: uevent. kobj %s.\n",kobj->name);  
  113.    
  114.     while( i< env->envp_idx){  
  115.         printk("%s.\n",env->envp[i]);  
  116.         i++;  
  117.     }  
  118.    
  119.     return 0;  
  120. }  
  121.    
  122. struct kset_uevent_ops uevent_ops =  
  123. {  
  124.     .filter = kset_filter,  
  125.     .name   = kset_name,  
  126.     .uevent = kset_uevent,  
  127. };  
  128.    
  129. struct kset *kset_parent;  
  130. struct kset kset_child;  
  131.    
  132. static int kset_test_init(void)  
  133. {  
  134.     printk("kboject test init.\n");  
  135.     kset_parent = kset_create_and_add("kset_parent", &uevent_ops, NULL);  
  136.     my_kobj.kobj.kset = kset_parent;  
  137.     kobject_init_and_add(&my_kobj.kobj,&ktype,NULL,"kobject_test");  
  138.    
  139.     kobject_set_name(&kset_child.kobj,"kset_child");  
  140.     kset_child.kobj.kset = kset_parent;  
  141.     kset_register(&kset_child);  
  142.       
  143.     return 0;  
  144. }  
  145.    
  146. static void kset_test_exit(void)  
  147. {  
  148.     printk("kobject test exit.\n");  
  149.     kobject_del(&my_kobj.kobj);  
  150.     kset_unregister(kset_parent);  
  151.     kset_unregister(&kset_child);  
  152. }  
  153.    
  154. module_init(kset_test_init);  
  155. module_exit(kset_test_exit);  
該模塊執行結果如下圖所示:
*************************************************************************************
函數的關係圖是tynew所加,個人喜歡從宏觀上把握函數的實現,如果想看詳細的實現,請繼續瀏覽
*************************************************************************************
kset的註冊使用kset_create_and_add函數,該函數定義如下:
  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的,該函數定義如下:
  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的定義如下:
  1. 771static struct kobj_type kset_ktype = {  
  2. 772    .sysfs_ops  = &kobj_sysfs_ops,  
  3. 773    .release = kset_release,  
  4. 774};  
爲了分析方便,我們先來看kset_release的定義:
  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函數:
  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函數定義如下:
  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函數定義如下:
  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函數,該函數定義如下:
  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事件。
  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函數定義如下:
  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函數,定義如下:
  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定義如下:
  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被創建和註冊到系統中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章