一个类是一个设备的高层视图,它抽象掉了底层的实现细节。例如,在驱动层面时,你可能会见到SCSI磁盘或者ATA磁盘;但在类层面时,它们都是磁盘。类允许用户空间基于它们做什么来使用设备,而不是它们如何被连接或者它们如何工作。 在《GSC3280的ADC子系统驱动模型(一)》的3.1,程序adc_class = class_create(THIS_MODULE, "adc");产生一个class,class_create()函数如下: | ||||
1. struct class { 2. const char *name; 3. struct module *owner; 4. 5. struct class_attribute *class_attrs; 6. struct device_attribute *dev_attrs; 7. struct bin_attribute *dev_bin_attrs; 8. struct kobject *dev_kobj; 9. 10. int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); 11. char *(*devnode)(struct device *dev, mode_t *mode); 12. 13. void (*class_release)(struct class *class); 14. void (*dev_release)(struct device *dev); 15. 16. int (*suspend)(struct device *dev, pm_message_t state); 17. int (*resume)(struct device *dev); 18. 19. const struct kobj_ns_type_operations *ns_type; 20. const void *(*namespace)(struct device *dev); 21. 22. const struct dev_pm_ops *pm; 23. 24. struct subsys_private *p; 25.}; 26.#define class_create(owner, name) \ 27.({ \ 28. static struct lock_class_key __key; \ 29. __class_create(owner, name, &__key); \ 30.}) 31.struct class *__class_create(struct module *owner, const char *name, 32. struct lock_class_key *key) 33.{ 34. struct class *cls; 35. int retval; 36. 37. cls = kzalloc(sizeof(*cls), GFP_KERNEL); 38. if (!cls) { 39. retval = -ENOMEM; 40. goto error; 41. } 42. 43. cls->name = name; 44. cls->owner = owner; 45. cls->class_release = class_create_release; 46. 47. retval = __class_register(cls, key); 48. if (retval) 49. goto error; 50. 51. return cls; 52. 53.error: 54. kfree(cls); 55. return ERR_PTR(retval); 56.} 57.int __class_register(struct class *cls, struct lock_class_key *key) 58.{ 59. struct subsys_private *cp; 60. int error; 61. 62. pr_debug("device class '%s': registering\n", cls->name); 63. 64. cp = kzalloc(sizeof(*cp), GFP_KERNEL); 65. if (!cp) 66. return -ENOMEM; 67. klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put); 68. INIT_LIST_HEAD(&cp->class_interfaces); 69. kset_init(&cp->glue_dirs); 70. __mutex_init(&cp->class_mutex, "struct class mutex", key); 71. error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); 72. if (error) { 73. kfree(cp); 74. return error; 75. } 76. 77. /* set the default /sys/dev directory for devices of this class */ 78. if (!cls->dev_kobj) 79. cls->dev_kobj = sysfs_dev_char_kobj; 80. 81.#if defined(CONFIG_BLOCK) 82. /* let the block class directory show up in the root of sysfs */ 83. if (!sysfs_deprecated || cls != &block_class) 84. cp->subsys.kobj.kset = class_kset; 85.#else 86. cp->subsys.kobj.kset = class_kset; 87.#endif 88. cp->subsys.kobj.ktype = &class_ktype; 89. cp->class = cls; 90. cls->p = cp; 91. 92. error = kset_register(&cp->subsys); 93. if (error) { 94. kfree(cp); 95. return error; 96. } 97. error = add_class_attrs(class_get(cls)); 98. class_put(cls); 99. return error; 100. }
1) class_create()函数是一个宏定义,具体调用了__class_create()函数。 2) __class_create()函数首先申请了一个class结构体内存,然后对其结构体成员变量赋值,最后调用__class_register()函数注册类。 3) __class_register()函数中,首先申请了结构体subsys_private内存,从class结构体成员可以看到,subsys_private是其一个成员指针。 4) 然后就是对subsys_private的成员变量初始化,注册subsys的kset,增加类属性等。 1. void __init adc_sysfs_init(struct class *adc_class) 2. { 3. adc_class->dev_attrs = adc_attrs; 4. } 说明: 1) 此处的类即是上面我们使用class_creat()创建的类。
1. int device_register(struct device *dev) 2. { 3. device_initialize(dev); 4. return device_add(dev); 5. } 6. void device_initialize(struct device *dev) 7. { 8. dev->kobj.kset = devices_kset; 9. kobject_init(&dev->kobj, &device_ktype); 10. INIT_LIST_HEAD(&dev->dma_pools); 11. mutex_init(&dev->mutex); 12. lockdep_set_novalidate_class(&dev->mutex); 13. spin_lock_init(&dev->devres_lock); 14. INIT_LIST_HEAD(&dev->devres_head); 15. device_pm_init(dev); 16. set_dev_node(dev, -1); 17.} 18.int device_add(struct device *dev) 19.{ 20. struct device *parent = NULL; 21. struct class_interface *class_intf; 22. int error = -EINVAL; 23. 24. dev = get_device(dev); 25. if (!dev) 26. goto done; 27. 28. if (!dev->p) { 29. error = device_private_init(dev); 30. if (error) 31. goto done; 32. } 33. 34. /* 35. * for statically allocated devices, which should all be converted 36. * some day, we need to initialize the name. We prevent reading back 37. * the name, and force the use of dev_name() 38. */ 39. if (dev->init_name) { 40. dev_set_name(dev, "%s", dev->init_name); 41. dev->init_name = NULL; 42. } 43. 44. if (!dev_name(dev)) { 45. error = -EINVAL; 46. goto name_error; 47. } 48. 49. pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 50. 51. parent = get_device(dev->parent); 52. setup_parent(dev, parent); 53. 54. /* use parent numa_node */ 55. if (parent) 56. set_dev_node(dev, dev_to_node(parent)); 57. 58. /* first, register with generic layer. */ 59. /* we require the name to be set before, and pass NULL */ 60. error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); 61. if (error) 62. goto Error; 63. 64. /* notify platform of device entry */ 65. if (platform_notify) 66. platform_notify(dev); 67. 68. error = device_create_file(dev, &uevent_attr); 69. if (error) 70. goto attrError; 71. 72. if (MAJOR(dev->devt)) { 73. error = device_create_file(dev, &devt_attr); 74. if (error) 75. goto ueventattrError; 76. 77. error = device_create_sys_dev_entry(dev); 78. if (error) 79. goto devtattrError; 80. 81. devtmpfs_create_node(dev); 82. } 83. 84. error = device_add_class_symlinks(dev); 85. if (error) 86. goto SymlinkError; 87. error = device_add_attrs(dev); 88. if (error) 89. goto AttrsError; 90. error = bus_add_device(dev); 91. if (error) 92. goto BusError; 93. error = dpm_sysfs_add(dev); 94. if (error) 95. goto DPMError; 96. device_pm_add(dev); 97. 98. /* Notify clients of device addition. This call must come 99. * after dpm_sysf_add() and before kobject_uevent(). 100. */ 101. if (dev->bus) 102. blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 103. BUS_NOTIFY_ADD_DEVICE, dev); 104. 105. kobject_uevent(&dev->kobj, KOBJ_ADD); 106. bus_probe_device(dev); 107. if (parent) 108. klist_add_tail(&dev->p->knode_parent, 109. &parent->p->klist_children); 110. 111. if (dev->class) { 112. mutex_lock(&dev->class->p->class_mutex); 113. /* tie the class to the device */ 114. klist_add_tail(&dev->knode_class, 115. &dev->class->p->klist_devices); 116. 117. /* notify any interfaces that the device is here */ 118. list_for_each_entry(class_intf, 119. &dev->class->p->class_interfaces, node) 120. if (class_intf->add_dev) 121. class_intf->add_dev(dev, class_intf); 122. mutex_unlock(&dev->class->p->class_mutex); 123. } 124. done: 125. put_device(dev); 126. return error; 127. DPMError: 128. bus_remove_device(dev); 129. BusError: 130. device_remove_attrs(dev); 131. AttrsError: 132. device_remove_class_symlinks(dev); 133. SymlinkError: 134. if (MAJOR(dev->devt)) 135. devtmpfs_delete_node(dev); 136. if (MAJOR(dev->devt)) 137. device_remove_sys_dev_entry(dev); 138. devtattrError: 139. if (MAJOR(dev->devt)) 140. device_remove_file(dev, &devt_attr); 141. ueventattrError: 142. device_remove_file(dev, &uevent_attr); 143. attrError: 144. kobject_uevent(&dev->kobj, KOBJ_REMOVE); 145. kobject_del(&dev->kobj); 146. Error: 147. cleanup_device_parent(dev); 148. if (parent) 149. put_device(parent); 150. name_error: 151. kfree(dev->p); 152. dev->p = NULL; 153. goto done; 154. } 说明: 1) device_register()函数首先调用device_initialize(dev);对dev成员初始化。 2) 然后调用device_add()函数增加设备。其中的device_add_attrs(dev)函数完成对类成员中的设备属性初始化,具体程序如下: 1. static int device_add_attrs(struct device *dev) 2. { 3. struct class *class = dev->class; 4. const struct device_type *type = dev->type; 5. int error; 6. 7. if (class) { 8. error = device_add_attributes(dev, class->dev_attrs); 9. if (error) 10. return error; 11. error = device_add_bin_attributes(dev, class->dev_bin_attrs); 12. if (error) 13. goto err_remove_class_attrs; 14. } 15. 16. if (type) { 17. error = device_add_groups(dev, type->groups); 18. if (error) 19. goto err_remove_class_bin_attrs; 20. } 21. 22. error = device_add_groups(dev, dev->groups); 23. if (error) 24. goto err_remove_type_groups; 25. 26. return 0; 27. 28. err_remove_type_groups: 29. if (type) 30. device_remove_groups(dev, type->groups); 31. err_remove_class_bin_attrs: 32. if (class) 33. device_remove_bin_attributes(dev, class->dev_bin_attrs); 34. err_remove_class_attrs: 35. if (class) 36. device_remove_attributes(dev, class->dev_attrs); 37. 38. return error; 39.} 说明: 1) 由上面可知,dev成员中有class成员,但是class中只有对dev_attrs赋值了,dev成员中没有groups成员,所以此处执行的函数为device_add_attributes(dev, class->dev_attrs),程序如下: 1. static int device_add_attributes(struct device *dev, 2. struct device_attribute *attrs) 3. { 4. int error = 0; 5. int i; 6. 7. if (attrs) { 8. for (i = 0; attr_name(attrs[i]); i++) { 9. error = device_create_file(dev, &attrs[i]); 10. if (error) 11. break; 12. } 13. if (error) 14. while (--i >= 0) 15. device_remove_file(dev, &attrs[i]); 16. } 17. return error; 18.} 说明: 1) 最后是调用device_create_file(dev, &attrs[i]);产生文件的。此函数在其他文章中会介绍。 | ||||
原文参见:http://blog.chinaunix.net/uid-25445243-id-4038871.html | ||||