zoukankan      html  css  js  c++  java
  • class.c 添加中文注释(2)

      1 /* Class Device Stuff */
      2 
      3 int class_device_create_file(struct class_device * class_dev,
      4                  const struct class_device_attribute * attr)
      5 {
      6     int error = -EINVAL;
      7     
      8     /* [cgw]: class_dev指针不为空 */
      9     if (class_dev)
     10         /* [cgw]: 为class_dev->kobj对象创建一个属性文件 */
     11         error = sysfs_create_file(&class_dev->kobj, &attr->attr);
     12     return error;
     13 }
     14 
     15 void class_device_remove_file(struct class_device * class_dev,
     16                   const struct class_device_attribute * attr)
     17 {
     18     /* [cgw]: class_dev指针不为空 */
     19     if (class_dev)
     20         /* [cgw]: 删除class_dev->kobj对象对应的一个属性文件 */
     21         sysfs_remove_file(&class_dev->kobj, &attr->attr);
     22 }
     23 
     24 int class_device_create_bin_file(struct class_device *class_dev,
     25                  struct bin_attribute *attr)
     26 {
     27     int error = -EINVAL;
     28 
     29     /* [cgw]: class_dev指针不为空 */
     30     if (class_dev)
     31         /* [cgw]: 为class_dev->kobj对象创建一个BIN文件 */
     32         error = sysfs_create_bin_file(&class_dev->kobj, attr);
     33     return error;
     34 }
     35 
     36 void class_device_remove_bin_file(struct class_device *class_dev,
     37                   struct bin_attribute *attr)
     38 {
     39     /* [cgw]: class_dev指针不为空 */
     40     if (class_dev)
     41         /* [cgw]: 删除class_dev->kobj对象对应的一个BIN文件 */
     42         sysfs_remove_bin_file(&class_dev->kobj, attr);
     43 }
     44 
     45 static ssize_t
     46 class_device_attr_show(struct kobject * kobj, struct attribute * attr,
     47                char * buf)
     48 {
     49     /* [cgw]: 找出包含这个attr的struct class_device_attribute *指针 */
     50     struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
     51     /* [cgw]: 找出包含这个kobj的struct class_device *指针
     52       */
     53     struct class_device * cd = to_class_dev(kobj);
     54     ssize_t ret = 0;
     55 
     56     /* [cgw]: class_dev_attr->show指针不为空 */
     57     if (class_dev_attr->show)
     58         /* [cgw]: 调用class_dev_attr->show方法 */
     59         ret = class_dev_attr->show(cd, buf);
     60     return ret;
     61 }
     62 
     63 static ssize_t
     64 class_device_attr_store(struct kobject * kobj, struct attribute * attr,
     65             const char * buf, size_t count)
     66 {
     67     /* [cgw]: 找出包含这个attr的struct class_device_attribute *指针 */
     68     struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
     69     /* [cgw]: 找出包含这个kobj的struct class_device *指针
     70       */
     71     struct class_device * cd = to_class_dev(kobj);
     72     ssize_t ret = 0;
     73 
     74     /* [cgw]: class_dev_attr->store指针不为空 */
     75     if (class_dev_attr->store)
     76         /* [cgw]: 调用class_dev_attr->store方法 */
     77         ret = class_dev_attr->store(cd, buf, count);
     78     return ret;
     79 }
     80 
     81 static struct sysfs_ops class_dev_sysfs_ops = {
     82     .show    = class_device_attr_show,
     83     .store    = class_device_attr_store,
     84 };
     85 
     86 static void class_dev_release(struct kobject * kobj)
     87 {
     88     /* [cgw]: 找出包含这个kobj的struct class_device *指针 */
     89     struct class_device *cd = to_class_dev(kobj);
     90     /* [cgw]: cls指向class_device的成员class */
     91     struct class * cls = cd->class;
     92 
     93     pr_debug("device class '%s': release.
    ", cd->class_id);
     94 
     95     /* [cgw]: 释放这个class_device的class_device_attribute内存空间
     96           * 并把class_device_attribute指针置为空
     97           */
     98     kfree(cd->devt_attr);
     99     cd->devt_attr = NULL;
    100 
    101     /* [cgw]: 调用class_device->release 方法,
    102           * 释放这个已分配的struct class_device *的内存空间
    103           */
    104     if (cd->release)
    105         cd->release(cd);
    106     else if (cls->release)
    107         /* [cgw]: 调用class_device->class->release 方法
    108               * 释放这个已分配的struct class *的内存空间
    109               */
    110         cls->release(cd);
    111     else {
    112         printk(KERN_ERR "Class Device '%s' does not have a release() function, "
    113             "it is broken and must be fixed.
    ",
    114             cd->class_id);
    115         WARN_ON(1);
    116     }
    117 }
    118 
    119 static struct kobj_type ktype_class_device = {
    120     .sysfs_ops    = &class_dev_sysfs_ops,
    121     .release    = class_dev_release,
    122 };
    123 
    124 static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
    125 {
    126     /* [cgw]: 找到kobj所属的类型ktype */
    127     struct kobj_type *ktype = get_ktype(kobj);
    128 
    129     /* [cgw]: 这个kobj的类型ktype属于ktype_class_device */
    130     if (ktype == &ktype_class_device) {
    131         /* [cgw]: 找到包含这个kobj 的class_dev指针
    132               */
    133         struct class_device *class_dev = to_class_dev(kobj);
    134         /* [cgw]: class_dev->class指针不为空 */
    135         if (class_dev->class)
    136             return 1;
    137     }
    138     return 0;
    139 }
    140 
    141 static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
    142 {
    143     /* [cgw]: 找到包含这个kobj 的class_dev指针
    144       */
    145     struct class_device *class_dev = to_class_dev(kobj);
    146 
    147     /* [cgw]: 返回class_dev下class的名字 */
    148     return class_dev->class->name;
    149 }
    150 
    151 #ifdef CONFIG_SYSFS_DEPRECATED
    152 char *make_class_name(const char *name, struct kobject *kobj)
    153 {
    154     char *class_name;
    155     int size;
    156     /* [cgw]: 找出这个kobj的名字
    157           * 计算两个字符串的总长度并+2,
    158           */
    159     size = strlen(name) + strlen(kobject_name(kobj)) + 2;
    160     /* [cgw]: 分配一个size字节的内存空间 */
    161     class_name = kmalloc(size, GFP_KERNEL);
    162     /* [cgw]: 分配失败 */
    163     if (!class_name)
    164         return NULL;
    165     /* [cgw] : 把名字name填装到class_name */
    166     strcpy(class_name, name);
    167     /* [cgw] : 在名字name末尾添加":" */
    168     strcat(class_name, ":");
    169     /* [cgw] : 合并字符串,name+":"+kobj->k_name */
    170     strcat(class_name, kobject_name(kobj));
    171     return class_name;
    172 }
    173 
    174 static int make_deprecated_class_device_links(struct class_device *class_dev)
    175 {
    176     char *class_name;
    177     int error;
    178 
    179     /* [cgw]: class_dev->dev指针为空 */
    180     if (!class_dev->dev)
    181         return 0;
    182     /* [cgw]: 合并class_dev->class->name和class_dev->kobj->k_name
    183           */
    184     class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
    185     /* [cgw]: 合并成功 */
    186     if (class_name)
    187         /* [cgw]: 在class_dev->dev->kobj对象目录下创建一个链表
    188               * 设置这个链表的名字为class_name
    189               */
    190         error = sysfs_create_link(&class_dev->dev->kobj,
    191                       &class_dev->kobj, class_name);
    192     else
    193         error = -ENOMEM;
    194     /* [cgw]: 释放class_name内存空间,class_name在这里只做临时作用 */
    195     kfree(class_name);
    196     return error;
    197 }
    198 
    199 static void remove_deprecated_class_device_links(struct class_device *class_dev)
    200 {
    201     char *class_name;
    202 
    203     /* [cgw]: class_dev->dev指针为空 */
    204     if (!class_dev->dev)
    205         return;
    206         
    207     /* [cgw]: 合并class_dev->class->name和class_dev->kobj->k_name
    208           */
    209     class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
    210     if (class_name)
    211         /* [cgw] : 从class_dev->dev->kobj对象目录下删除一个名字为
    212               * class_name的链表
    213               */
    214         sysfs_remove_link(&class_dev->dev->kobj, class_name);
    215     /* [cgw] : 释放class_name的内存空间 */
    216     kfree(class_name);
    217 }
    218 #else
    219 static inline int make_deprecated_class_device_links(struct class_device *cd)
    220 { return 0; }
    221 static void remove_deprecated_class_device_links(struct class_device *cd)
    222 { }
    223 #endif
    224 
    225 static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
    226              int num_envp, char *buffer, int buffer_size)
    227 {
    228     /* [cgw]: 找出包含这个kobj的class_device结构体指针 */
    229     struct class_device *class_dev = to_class_dev(kobj);
    230     struct device *dev = class_dev->dev;
    231     int i = 0;
    232     int length = 0;
    233     int retval = 0;
    234 
    235     pr_debug("%s - name = %s
    ", __FUNCTION__, class_dev->class_id);
    236 
    237     /* [cgw]: 主设备号不为0 */
    238     if (MAJOR(class_dev->devt)) {
    239         /* [cgw]: 格式化"MAJOR= MAJOR(class_dev->devt)"填装到buffer中
    240               * 并把buffer指针储存在envp数组
    241               */
    242         add_uevent_var(envp, num_envp, &i,
    243                    buffer, buffer_size, &length,
    244                    "MAJOR=%u", MAJOR(class_dev->devt));
    245 
    246         /* [cgw]: 格式化"MAJOR= MINOR(class_dev->devt)"填装到buffer中
    247               * 并把buffer指针储存在envp数组
    248               */
    249         add_uevent_var(envp, num_envp, &i,
    250                    buffer, buffer_size, &length,
    251                    "MINOR=%u", MINOR(class_dev->devt));
    252     }
    253 
    254     /* [cgw]: dev指针不为空 */
    255     if (dev) {
    256         /* [cgw]: 获得dev->kobj所在的路径 */
    257         const char *path = kobject_get_path(&, GFP_KERNEL);
    258         /* [cgw]: 获取成功 */
    259         if (path) {
    260             /* [cgw]: 格式化"PHYSDEVPATH=path"填装到buffer中
    261                       * 并把buffer指针储存在环境变量envp数组,i+1
    262                       */
    263             add_uevent_var(envp, num_envp, &i,
    264                        buffer, buffer_size, &length,
    265                        "PHYSDEVPATH=%s", path);
    266             /* [cgw]: 释放path的内存空间 */
    267             kfree(path);
    268         }
    269 
    270         /* [cgw]: dev->bus指针不为空 */
    271         if (dev->bus)
    272             /* [cgw]: 格式化"PHYSDEVBUS=dev->bus->name"填装到buffer中
    273                       * 并把buffer指针储存在环境变量envp数组,i+1
    274                       */
    275             add_uevent_var(envp, num_envp, &i,
    276                        buffer, buffer_size, &length,
    277                        "PHYSDEVBUS=%s", dev->bus->name);
    278 
    279         /* [cgw]: dev->driver指针不为空 */
    280         if (dev->driver)
    281             /* [cgw]: 格式化"PHYSDEVDRIVER=dev->driver->name"填装到buffer中
    282                       * 并把buffer指针储存在环境变量envp数组,i+1
    283                       */
    284             add_uevent_var(envp, num_envp, &i,
    285                        buffer, buffer_size, &length,
    286                        "PHYSDEVDRIVER=%s", dev->driver->name);
    287     }
    288 
    289     /* terminate, set to next free slot, shrink available space */
    290     /* [cgw]: 清空下一个环境变量,envp[i]是一个指针,把这个指针置0 */
    291     envp[i] = NULL;
    292     /* [cgw]: 重置envp的指针,指向下一个环境变量envp[i] */
    293     envp = &envp[i];
    294     /* [cgw]: 计算环境变量数组剩下的可用大小 */
    295     num_envp -= i;
    296     /* [cgw]: 重置buffer指针,指向buffer + length */
    297     buffer = &buffer[length];
    298     /* [cgw]: 计算环境变量buffer剩下的可用大小 */
    299     buffer_size -= length;
    300 
    301     /* [cgw]: class_dev->uevent指针不为空 */
    302     if (class_dev->uevent) {
    303         /* have the class device specific function add its stuff */
    304         /* [cgw]: 调用class_dev->uevent方法 */
    305         retval = class_dev->uevent(class_dev, envp, num_envp,
    306                         buffer, buffer_size);
    307         if (retval)
    308             pr_debug("class_dev->uevent() returned %d
    ", retval);
    309     } else if (class_dev->class->uevent) {
    310         /* have the class specific function add its stuff */
    311         /* [cgw]: 调用class_dev->class->uevent方法 */
    312         retval = class_dev->class->uevent(class_dev, envp, num_envp,
    313                            buffer, buffer_size);
    314         if (retval)
    315             pr_debug("class->uevent() returned %d
    ", retval);
    316     }
    317 
    318     return retval;
    319 }
    320 
    321 static struct kset_uevent_ops class_uevent_ops = {
    322     .filter =    class_uevent_filter,
    323     .name =        class_uevent_name,
    324     .uevent =    class_uevent,
    325 };
    326 
    327 static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);
    328 
    329 
    330 static int class_device_add_attrs(struct class_device * cd)
    331 {
    332     int i;
    333     int error = 0;
    334     struct class * cls = cd->class;
    335 
    336     /* [cgw]: cls->class_dev_attrs指针不为空,即分配了class device 的属性 */
    337     if (cls->class_dev_attrs) {
    338         /* [cgw]: 历遍class_dev_attrs[]数组,如果该属性名字不为空,则
    339               * 对应地创建一个属性文件
    340               */
    341         for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
    342             /* [cgw]: 创建一个class device属性文件 */
    343             error = class_device_create_file(cd,
    344                              &cls->class_dev_attrs[i]);
    345             if (error)
    346                 goto Err;
    347         }
    348     }
    349  Done:
    350     return error;
    351  Err:
    352     /* [cgw]: 删除class device的所有属性文件 */
    353     while (--i >= 0)
    354         class_device_remove_file(cd,&cls->class_dev_attrs[i]);
    355     goto Done;
    356 }
    357 
    358 static void class_device_remove_attrs(struct class_device * cd)
    359 {
    360     int i;
    361     struct class * cls = cd->class;
    362 
    363     /* [cgw]: cls->class_dev_attrs指针不为空,即此前已经添加了这个属性列表 */
    364     if (cls->class_dev_attrs) {
    365         /* [cgw]: 历遍class_dev_attrs[]数组,如果该属性名字不为空,则
    366               * 对应地删除一个属性文件
    367               */
    368         for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
    369             /* [cgw]: 删除一个属性文件 */
    370             class_device_remove_file(cd,&cls->class_dev_attrs[i]);
    371     }
    372 }
    373 
    374 static int class_device_add_groups(struct class_device * cd)
    375 {
    376     int i;
    377     int error = 0;
    378 
    379     /* [cgw]: cd->groups指针不为空 */
    380     if (cd->groups) {
    381         /* [cgw]: 历遍groups[],对应每个groups创建一个属性组 */
    382         for (i = 0; cd->groups[i]; i++) {
    383             /* [cgw]: 创建一个属性组 */
    384             error = sysfs_create_group(&cd->kobj, cd->groups[i]);
    385             /* [cgw]: 创建失败 */
    386             if (error) {
    387                 /* [cgw]: 删除所有属性组 */
    388                 while (--i >= 0)
    389                     /* [cgw]: 删除一个属性组 */
    390                     sysfs_remove_group(&cd->kobj, cd->groups[i]);
    391                 goto out;
    392             }
    393         }
    394     }
    395 out:
    396     return error;
    397 }
    398 
    399 static void class_device_remove_groups(struct class_device * cd)
    400 {
    401     int i;
    402     /* [cgw]: cd->groups指针不为空 */
    403     if (cd->groups) {
    404         /* [cgw]: 历遍groups[],删除所有属性组 */
    405         for (i = 0; cd->groups[i]; i++) {
    406             /* [cgw]: 删除一个属性组 */
    407             sysfs_remove_group(&cd->kobj, cd->groups[i]);
    408         }
    409     }
    410 }
    411 
    412 static ssize_t show_dev(struct class_device *class_dev, char *buf)
    413 {
    414     /* [cgw]: 格式化class_dev->devt的主和次设备号为字符串,
    415           * 填装到buf中
    416           */
    417     return print_dev_t(buf, class_dev->devt);
    418 }
    419 
    420 static ssize_t store_uevent(struct class_device *class_dev,
    421                 const char *buf, size_t count)
    422 {
    423     /* [cgw]: 对class_dev->kobj产生一个KOBJ_ADD事件通知用户空间 */
    424     kobject_uevent(&class_dev->kobj, KOBJ_ADD);
    425     return count;
    426 }
    427 
    428 void class_device_initialize(struct class_device *class_dev)
    429 {
    430     /* [cgw]: 分配class_dev->kobj.kset,指向&class_obj_subsys */
    431     kobj_set_kset_s(class_dev, class_obj_subsys);
    432     /* [cgw]: 初始化class_dev->kobj */
    433     kobject_init(&class_dev->kobj);
    434     /* [cgw]: 初始化class_dev->node链表 */
    435     INIT_LIST_HEAD(&class_dev->node);
    436 }
    437 
    438 int class_device_add(struct class_device *class_dev)
    439 {
    440     struct class *parent_class = NULL;
    441     struct class_device *parent_class_dev = NULL;
    442     struct class_interface *class_intf;
    443     int error = -EINVAL;
    444 
    445     /* [cgw]: class_dev->kobj引用计数+1 
    446           * 并根据kobj找到包含这个kobj的结构体指针class_dev
    447           */
    448     class_dev = class_device_get(class_dev);
    449     /* [cgw]: class_dev指针为空 */
    450     if (!class_dev)
    451         return -EINVAL;
    452 
    453     /* [cgw]: class_dev->class_id长度为0 */
    454     if (!strlen(class_dev->class_id))
    455         goto out1;
    456 
    457     /* [cgw]: class->kobj引用计数+1 
    458           * 并根据kobj找到包含这个kobj的结构体指针class
    459           */
    460     parent_class = class_get(class_dev->class);
    461     /* [cgw]: parent_class指针为空 */
    462     if (!parent_class)
    463         goto out1;
    464 
    465     /* [cgw]: 找出class_dev的父节点,并且class_dev->parent->kobj
    466           * 引用计数+1
    467           */
    468     parent_class_dev = class_device_get(class_dev->parent);
    469 
    470     pr_debug("CLASS: registering class device: ID = '%s'
    ",
    471          class_dev->class_id);
    472 
    473     /* first, register with generic layer. */
    474     /* [cgw]: 以class_dev->class_id作为class_dev->kobj的名字 */
    475     error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
    476     /* [cgw]: 设置class_dev->kobj的名字失败 */
    477     if (error)
    478         goto out2;
    479 
    480     /* [cgw]: parent_class_dev指针不为空 */
    481     if (parent_class_dev)
    482         /* [cgw]: 设置class_dev的kobj的父节点为class_dev父节点的kobj */
    483         class_dev->kobj.parent = &parent_class_dev->kobj;
    484     else
    485         /* [cgw]: 设置class_dev的kobj的父节点为class->subsys.kobj 
    486               * 设置class_dev的kobj的在最顶层,父节点就是kset.kobj
    487               */
    488         class_dev->kobj.parent = &parent_class->subsys.kobj;
    489 
    490     /* [cgw]: 添加kobj到层,实际上是把kobj添加到kset集合
    491           * entry插入到kobj->kset->list链表中, 为这个kobj创建目录,
    492           * 即加入到sysfs目录,并为这个kobj添加属性
    493           */
    494     error = kobject_add(&class_dev->kobj);
    495     /* [cgw]: 添加失败 */
    496     if (error)
    497         goto out2;
    498 
    499     /* add the needed attributes to this device */
    500     /* [cgw]: 在class_dev->kobj目录下创建一个名为subsystem
    501       * 的链表,指向parent_class->subsys.kobj
    502       */
    503     error = sysfs_create_link(&class_dev->kobj,
    504                   &parent_class->subsys.kobj, "subsystem");
    505     /* [cgw]: 创建失败 */
    506     if (error)
    507         goto out3;
    508     /* [cgw]: 设置class_dev的属性名为uevent */
    509     class_dev->uevent_attr.attr.name = "uevent";
    510     /* [cgw]: 权限为S_IWUSR */
    511     class_dev->uevent_attr.attr.mode = S_IWUSR;
    512     /* [cgw]: 设置拥有这个class_dev->uevent_attr属性的模块 */
    513     class_dev->uevent_attr.attr.owner = parent_class->owner;
    514     /* [cgw]: 分配class_dev->uevent_attr.store的方法 */
    515     class_dev->uevent_attr.store = store_uevent;
    516     /* [cgw]: 为class_dev->kobj创建一个属性为class_dev->uevent_attr的
    517       * 属性文件
    518       */
    519     error = class_device_create_file(class_dev, &class_dev->uevent_attr);
    520     /* [cgw]: 创建失败 */
    521     if (error)
    522         goto out3;
    523     /* [cgw]: 主设备号不为0 */
    524     if (MAJOR(class_dev->devt)) {
    525         struct class_device_attribute *attr;
    526         /* [cgw]: 分配一块sizeof(*attr)字节大小的内存空间 */
    527         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
    528         /* [cgw]: 分配失败 */
    529         if (!attr) {
    530             error = -ENOMEM;
    531             goto out4;
    532         }
    533         /* [cgw]: attr的属性名为dev */
    534         attr->attr.name = "dev";
    535         /* [cgw]: attr的权限为S_IRUGO */
    536         attr->attr.mode = S_IRUGO;
    537         /* [cgw]: 设置拥有这个attr->attr属性的模块 */
    538         attr->attr.owner = parent_class->owner;
    539         /* [cgw]: 分配attr->show的方法 */
    540         attr->show = show_dev;
    541         /* [cgw]: 为class_dev->kobj对象创建一个attr属性文件 */
    542         error = class_device_create_file(class_dev, attr);
    543         /* [cgw]: 创建失败 */
    544         if (error) {
    545             /* [cgw]: 释放attr的内存空间 */
    546             kfree(attr);
    547             goto out4;
    548         }
    549         /* [cgw]: class_dev->devt_attr指向attr */
    550         class_dev->devt_attr = attr;
    551     }
    552 
    553     /* [cgw]: 为class_dev->kobj添加属性文件列表,属性文件
    554           * 来自于class_dev->class->class_dev_attrs[]
    555           */
    556     error = class_device_add_attrs(class_dev);
    557     /* [cgw]: 添加失败 */
    558     if (error)
    559         goto out5;
    560 
    561     /* [cgw]: class_dev->dev指针不为空 */
    562     if (class_dev->dev) {
    563         /* [cgw]: 在class_dev->kobj目录下创建一个名为device的链表
    564               * 指向class_dev->dev->kobj
    565               */
    566         error = sysfs_create_link(&class_dev->kobj,
    567                       &class_dev->dev->kobj, "device");
    568         /* [cgw]: 创建失败 */
    569         if (error)
    570             goto out6;
    571     }
    572 
    573     /* [cgw]: 添加属性组 */
    574     error = class_device_add_groups(class_dev);
    575     /* [cgw]: 添加失败 */
    576     if (error)
    577         goto out7;
    578 
    579     /* [cgw]: 合并class_dev->class->name和class_dev->kobj->k_name
    580           * class_dev->dev->kobj对象目录下创建一个链表
    581           */
    582     error = make_deprecated_class_device_links(class_dev);
    583     /* [cgw]: 创建失败 */
    584     if (error)
    585         goto out8;
    586 
    587     /* [cgw]: 通知用户空间,产生一个KOBJ_ADD事件 */ 
    588     kobject_uevent(&class_dev->kobj, KOBJ_ADD);
    589 
    590     /* notify any interfaces this device is now here */
    591     /* [cgw]: 获得信号量 */
    592     down(&parent_class->sem);
    593     /* [cgw]: 插入一个新节点class_dev->node到parent_class->children节点前 */
    594     list_add_tail(&class_dev->node, &parent_class->children);
    595     /* [cgw]: 从parent_class->interfaces的下一节点起,历遍这个链表,直到又回到
    596       * 头节点(环形链表)
    597       */
    598     list_for_each_entry(class_intf, &parent_class->interfaces, node) {
    599         /* [cgw]: 这个节点的class_intf->add的指针不为空 */
    600         if (class_intf->add)
    601             /* [cgw]: 调用class_intf->add方法 */
    602             class_intf->add(class_dev, class_intf);
    603     }
    604     /* [cgw]: 释放信号量 */
    605     up(&parent_class->sem);
    606 
    607     goto out1;
    608 
    609  out8:
    610     /* [cgw]: 删除属性组 */
    611     class_device_remove_groups(class_dev);
    612  out7:
    613     /* [cgw]: class_dev->dev指针不为空 */
    614     if (class_dev->dev)
    615         /* [cgw]: 删除class_dev->kobj目录下,名为device的链表 */
    616         sysfs_remove_link(&class_dev->kobj, "device");
    617  out6:
    618     /* [cgw]: 删除class_dev所有属性文件 */
    619     class_device_remove_attrs(class_dev);
    620  out5:
    621     /* [cgw]: class_dev->devt_attr指针不为空,即已经分配了class_dev->devt_attr属性 */
    622     if (class_dev->devt_attr)
    623         /* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->devt_attr属性文件 */
    624         class_device_remove_file(class_dev, class_dev->devt_attr);
    625  out4:
    626     /* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->uevent_attr属性文件 */
    627     class_device_remove_file(class_dev, &class_dev->uevent_attr);
    628  out3:
    629     /* [cgw]: 删除class_dev->kobj,从sysfs中删除对应class_dev->kobj的
    630           * 条目
    631           */
    632     kobject_del(&class_dev->kobj);
    633  out2:
    634     /* [cgw]: parent_class_dev指针不为空(class_dev->parent) */
    635     if(parent_class_dev)
    636         /* [cgw]: parent_class_dev->kobj引用计数-1 */
    637         class_device_put(parent_class_dev);
    638     /* [cgw]: parent_class->subsys.kset.kobj引用计数-1 */
    639     class_put(parent_class);
    640  out1:
    641     /* [cgw]: class_dev->kobj引用计数-1 */
    642     class_device_put(class_dev);
    643     return error;
    644 }
  • 相关阅读:
    django实现github第三方本地登录
    django扩展User模型(model),profile
    WSGI
    Linux查看配置文件中未被注释的有效配置行
    virsh 命令
    qemu-img命令
    python logging
    oslo.messaging
    集成kafka的身份认证(SASL/PLAIN)到kubernets环境中
    Helm基础知识
  • 原文地址:https://www.cnblogs.com/hackfun/p/5811395.html
Copyright © 2011-2022 走看看