Linux设备模型分析之bus --转
时间:10-02
整理:3721RD
点击:
Linux设备模型分析之bus
内核版本:2.6.36
前面我们分析了linux设备模型中kobject、kset以及ktype的使用,它们是设备模型的最基础部分,在其上有更高级一层的bus、device和driver。在这一篇文章中,我们来看一下bus的用法。 一、相关数据结构首先,我们列出本文涉及的相关数据结构。[cpp] view plaincopyprint?
二、注册busbus的注册接口为bus_register,该函数代码如下:[cpp] view plaincopyprint?
894行,设置priv->subsys.kobj的名字,priv->subsys是一个kset,代表这个bus。bus是通过一个kset来表示的,而device和device_driver都是通过一个kobject来表示的,由此也可以看出他们的不同。898行,设置priv->subsys.kobj.kset为bus_kset;在drivers/base/bus.c文件中,162行有如下定义:[cpp] view plaincopyprint?
162static struct kset *bus_kset;
同时,在buses_init函数中对bus_kset进行了初始化:[cpp] view plaincopyprint?
1056行,创建一个名为bus的kset,赋值给bus_kset,对应/sys/bus目录。所有的bus都属性bus_set,即所有的bus对应的sys系统目录都放在/sys/bus目录下。bus_kset对应的kset_uevent_ops是bus_uevent_ops,其定义如下:[cpp] view plaincopyprint?
158static const struct kset_uevent_ops bus_uevent_ops = {159 .filter = bus_uevent_filter,160};
bus_uevent_filter函数定义如下:[cpp] view plaincopyprint?
回忆一下上一篇博客《Linux设备模型分析之kset》介绍的内容,如果kset_uevent_ops.filter函数返回0,将不会处理uevent事件。在bus_uevent_filter函数中,如果kobj->ktype不是bus_ktype,则返回0,即不处理Uevent事件。bus_ktype定义如下:[cpp] view plaincopyprint?
145static struct kobj_type bus_ktype = {146 .sysfs_ops = &bus_sysfs_ops,147};
bus_sysfs_ops定义如下:[cpp] view plaincopyprint?
119static const struct sysfs_ops bus_sysfs_ops = {120 .show = bus_attr_show,121 .store = bus_attr_store,122};
bus_attr_show和bus_attr_store函数定义如下:[cpp] view plaincopyprint?
bus_attribute结构体定义如下:[cpp] view plaincopyprint?
回到bus_register函数:899行,设置priv->subsys.kobj.ktype为 &bus_ktype;回忆一下前面的文章《Linux设备模型分析之kobject》,对kobject属性的读写操作将调用kobject.ktype定义的sysfs_ops函数集指定的show和store函数。所以对bus属性文件的读写操作将会调用bus_ktyp.sysfs_ops指定的bus_attr_show和bus_attr_store函数,这两个函数我们前面已经分析过了,他们将回溯到bus_attr->show和bus_attr->store函数。900行,设置priv->drivers_autoprobe为1;902行,调用kset_register注册priv->subsys,即注册代表bus的kset。注册完成后,将在/sys/bus目录下出现对应该bus的目录。906行,调用bus_create_file(bus, &bus_attr_uevent),创建uevent属性文件,该函数定义如下:[cpp] view plaincopyprint?
128行,调用sysfs_create_file函数创建了bus_attribute对应的属性文件。先来看bus_attr_uevent的定义,它是通过宏BUS_ATTR生成的:[cpp] view plaincopyprint?
870static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
BUS_ATTR定义如下:[cpp] view plaincopyprint?
44#define BUS_ATTR(_name, _mode, _show, _store) \45struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
__ATTR定义如下:[cpp] view plaincopyprint?
70#define __ATTR(_name,_mode,_show,_store) { \71 .attr = {.name = __stringify(_name), .mode = _mode }, \72 .show = _show, \73 .store = _store, \74}
从bus_attr_uevent的定义可以看出,对应的uevent属性只有store接口,没有实现show接口。store接口函数bus_uevent_store定义如下:[cpp] view plaincopyprint?
回到bus_register函数:910 - 915行,创建名为devices的kset,其parent是priv->subsys.kobj,即在相应bus目录下创建一个devices目录。917 - 922行,创建名为drivers的kset,其parent是priv->subsys.kobj,即在相应bus目录下创建一个drivers目录。924行,初始化priv->klist_devices,即devices链表。925行,初始化priv->klist_drivers,即drivers链表。927行,调用add_probe_files(bus)函数创建drivers_probe和drivers_autoprobe两个属性文件,该函数定义如下:[cpp] view plaincopyprint?
bus_create_file函数我们前面已经分析过了,610行,创建drivers_probe属性文件,614行,创建drivers_autoprobe属性文件。其对应的bus_attribute定义如下:[cpp] view plaincopyprint?
602static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);603static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,604 show_drivers_autoprobe, store_drivers_autoprobe);
属性文件对应的操作函数定义如下:[cpp] view plaincopyprint?
show_drivers_autoprobe函数用于显示bus->p->drivers_autoprobe的值。store_drivers_autoprobe函数根据用户的要求设置bus->p->drivers_autoprobe的值。store_drivers_probe函数245行调用bus_find_device_by_name 在bus上查找用户指定的device,并且在248行调用bus_rescan_devices_helper函数查找匹配device_driver.回到bus_register函数:931行,调用bus_add_attrs函数创建bus默认属性文件,该函数定义如下:[cpp] view plaincopyprint?
820 - 826行,如果bus->bus_attrs指定了bus的默认属性,则创建对应的属性文件。
内核版本:2.6.36
前面我们分析了linux设备模型中kobject、kset以及ktype的使用,它们是设备模型的最基础部分,在其上有更高级一层的bus、device和driver。在这一篇文章中,我们来看一下bus的用法。 一、相关数据结构首先,我们列出本文涉及的相关数据结构。[cpp] view plaincopyprint?
- 52 const char *name;
53 struct bus_attribute *bus_attrs; - 54 struct device_attribute *dev_attrs;
55 struct driver_attribute *drv_attrs; - 56
57 int (*match)(struct device *dev, struct device_driver *drv); - 58 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
59 int (*probe)(struct device *dev); - 60 int (*remove)(struct device *dev);
61 void (*shutdown)(struct device *dev); - 62
63 int (*suspend)(struct device *dev, pm_message_t state); - 64 int (*resume)(struct device *dev);
65 - 66 const struct dev_pm_ops *pm;
67 - 68 struct bus_type_private *p;
69}; -
38struct bus_attribute { - 39 struct attribute attr;
40 ssize_t (*show)(struct bus_type *bus, char *buf); - 41 ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
42}; -
336/* interface for exporting device attributes */ - 337struct device_attribute {
338 struct attribute attr; - 339 ssize_t (*show)(struct device *dev, struct device_attribute *attr,
340 char *buf); - 341 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
342 const char *buf, size_t count); - 343};
- 162struct driver_attribute {
163 struct attribute attr; - 164 ssize_t (*show)(struct device_driver *driver, char *buf);
165 ssize_t (*store)(struct device_driver *driver, const char *buf, - 166 size_t count);
167}; -
2/** - 3 * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
4 * - 5 * @subsys - the struct kset that defines this bus. This is the main kobject
6 * @drivers_kset - the list of drivers associated with this bus - 7 * @devices_kset - the list of devices associated with this bus
8 * @klist_devices - the klist to iterate over the @devices_kset - 9 * @klist_drivers - the klist to iterate over the @drivers_kset
10 * @bus_notifier - the bus notifier list for anything that cares about things - 11 * on this bus.
12 * @bus - pointer back to the struct bus_type that this structure is associated - 13 * with.
14 * - 15 * This structure is the one that is the actual kobject allowing struct
16 * bus_type to be statically allocated safely. Nothing outside of the driver - 17 * core should ever touch these fields.
18 */ - 19struct bus_type_private {
20 struct kset subsys; - 21 struct kset *drivers_kset;
22 struct kset *devices_kset; - 23 struct klist klist_devices;
24 struct klist klist_drivers; - 25 struct blocking_notifier_head bus_notifier;
26 unsigned int drivers_autoprobe:1; - 27 struct bus_type *bus;
28}; -
406struct device { - 407 struct device *parent;
408 - 409 struct device_private *p;
410 - 411 struct kobject kobj;
412 const char *init_name; /* initial name of the device */ - 413 struct device_type *type;
414 - 415 struct mutex mutex; /* mutex to synchronize calls to
416 * its driver. - 417 */
418 - 419 struct bus_type *bus; /* type of bus device is on */
420 struct device_driver *driver; /* which driver has allocated this - 421 device */
422 void *platform_data; /* Platform specific data, device - 423 core doesn't touch it */
424 struct dev_pm_info power; - 425
426#ifdef CONFIG_NUMA - 427 int numa_node; /* NUMA node this device is close to */
428#endif - 429 u64 *DMA_mask; /* dma mask (if dma'able device) */
430 u64 coherent_dma_mask;/* Like dma_mask, but for - 431 alloc_coherent mappings as
432 not all hardware supports - 433 64 bit addresses for consistent
434 allocations such descriptors. */ - 435
436 struct device_dma_parameters *dma_pARMs; - 437
438 struct list_head dma_pools; /* dma pools (if dma'ble) */ - 439
440 struct dma_coherent_mem *dma_mem; /* internal for coherent mem - 441 override */
442 /* arch specific additions */ - 443 struct dev_archdata archdata;
444#ifdef CONFIG_OF - 445 struct device_node *of_node;
446#endif - 447
448 dev_t devt; /* dev_t, creates the sysfs "dev" */ - 449
450 SPInlock_t devres_lock; - 451 struct list_head devres_head;
452 - 453 struct klist_node knode_class;
454 struct class *class; - 455 const struct attribute_group **groups; /* optional groups */
456 - 457 void (*release)(struct device *dev);
458}; -
123struct device_driver { - 124 const char *name;
125 struct bus_type *bus; - 126
127 struct module *owner; - 128 const char *mod_name; /* used for built-in modules */
129 - 130 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
131 - 132#if defined(CONFIG_OF)
133 const struct of_device_id *of_match_table; - 134#endif
135 - 136 int (*probe) (struct device *dev);
137 int (*remove) (struct device *dev); - 138 void (*shutdown) (struct device *dev);
139 int (*suspend) (struct device *dev, pm_message_t state); - 140 int (*resume) (struct device *dev);
141 const struct attribute_group **groups; - 142
143 const struct dev_pm_ops *pm; - 144
145 struct driver_private *p; - 146};
51struct bus_type {
二、注册busbus的注册接口为bus_register,该函数代码如下:[cpp] view plaincopyprint?
- 873 * bus_register - register a bus with the system.
874 * @bus: bus. - 875 *
876 * Once we have that, we registered the bus with the kobject - 877 * infrastructure, then register the children subsystEMS it has:
878 * the devices and drivers that belong to the bus. - 879 */
880int bus_register(struct bus_type *bus) - 881{
882 int retval; - 883 struct bus_type_private *priv;
884 - 885 priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
886 if (!priv) - 887 return -ENOMEM;
888 - 889 priv->bus = bus;
890 bus->p = priv; - 891
892 BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); - 893
894 retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); - 895 if (retval)
896 goto out; - 897
898 priv->subsys.kobj.kset = bus_kset; - 899 priv->subsys.kobj.ktype = &bus_ktype;
900 priv->drivers_autoprobe = 1; - 901
902 retval = kset_register(&priv->subsys); - 903 if (retval)
904 goto out; - 905
906 retval = bus_create_file(bus, &bus_attr_uevent); - 907 if (retval)
908 goto bus_uevent_fail; - 909
910 priv->devices_kset = kset_create_and_add("devices", NULL, - 911 &priv->subsys.kobj);
912 if (!priv->devices_kset) { - 913 retval = -ENOMEM;
914 goto bus_devices_fail; - 915 }
916 - 917 priv->drivers_kset = kset_create_and_add("drivers", NULL,
918 &priv->subsys.kobj); - 919 if (!priv->drivers_kset) {
920 retval = -ENOMEM; - 921 goto bus_drivers_fail;
922 } - 923
924 klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); - 925 klist_init(&priv->klist_drivers, NULL, NULL);
926 - 927 retval = add_probe_files(bus);
928 if (retval) - 929 goto bus_probe_files_fail;
930 - 931 retval = bus_add_attrs(bus);
932 if (retval) - 933 goto bus_attrs_fail;
934 - 935 pr_debug("bus: '%s': registered\n", bus->name);
936 return 0; - 937
938bus_attrs_fail: - 939 remove_probe_files(bus);
940bus_probe_files_fail: - 941 kset_unregister(bus->p->drivers_kset);
942bus_drivers_fail: - 943 kset_unregister(bus->p->devices_kset);
944bus_devices_fail: - 945 bus_remove_file(bus, &bus_attr_uevent);
946bus_uevent_fail: - 947 kset_unregister(&bus->p->subsys);
948out: - 949 kfree(bus->p);
950 bus->p = NULL; - 951 return retval;
- 952}
872/**
894行,设置priv->subsys.kobj的名字,priv->subsys是一个kset,代表这个bus。bus是通过一个kset来表示的,而device和device_driver都是通过一个kobject来表示的,由此也可以看出他们的不同。898行,设置priv->subsys.kobj.kset为bus_kset;在drivers/base/bus.c文件中,162行有如下定义:[cpp] view plaincopyprint?
- 162static struct kset *bus_kset;
162static struct kset *bus_kset;
同时,在buses_init函数中对bus_kset进行了初始化:[cpp] view plaincopyprint?
- 1055{
1056 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); - 1057 if (!bus_kset)
1058 return -ENOMEM; - 1059 return 0;
- 1060}
1054int __init buses_init(void)
1056行,创建一个名为bus的kset,赋值给bus_kset,对应/sys/bus目录。所有的bus都属性bus_set,即所有的bus对应的sys系统目录都放在/sys/bus目录下。bus_kset对应的kset_uevent_ops是bus_uevent_ops,其定义如下:[cpp] view plaincopyprint?
- 159 .fiLTEr = bus_uevent_filter,
- 160};
158static const struct kset_uevent_ops bus_uevent_ops = {
158static const struct kset_uevent_ops bus_uevent_ops = {159 .filter = bus_uevent_filter,160};
bus_uevent_filter函数定义如下:[cpp] view plaincopyprint?
- 150{
151 struct kobj_type *ktype = get_ktype(kobj); - 152
153 if (ktype == &bus_ktype) - 154 return 1;
155 return 0; - 156}
149static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
回忆一下上一篇博客《Linux设备模型分析之kset》介绍的内容,如果kset_uevent_ops.filter函数返回0,将不会处理uevent事件。在bus_uevent_filter函数中,如果kobj->ktype不是bus_ktype,则返回0,即不处理Uevent事件。bus_ktype定义如下:[cpp] view plaincopyprint?
- 146 .sysfs_ops = &bus_sysfs_ops,
- 147};
145static struct kobj_type bus_ktype = {
145static struct kobj_type bus_ktype = {146 .sysfs_ops = &bus_sysfs_ops,147};
bus_sysfs_ops定义如下:[cpp] view plaincopyprint?
- 120 .show = bus_attr_show,
121 .store = bus_attr_store, - 122};
119static const struct sysfs_ops bus_sysfs_ops = {
119static const struct sysfs_ops bus_sysfs_ops = {120 .show = bus_attr_show,121 .store = bus_attr_store,122};
bus_attr_show和bus_attr_store函数定义如下:[cpp] view plaincopyprint?
- 96 char *buf)
97{ - 98 struct bus_attribute *bus_attr = to_bus_attr(attr);
99 struct bus_type_private *bus_priv = to_bus(kobj); - 100 ssize_t ret = 0;
101 - 102 if (bus_attr->show)
103 ret = bus_attr->show(bus_priv->bus, buf); - 104 return ret;
105} - 106
107static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr, - 108 const char *buf, size_t count)
109{ - 110 struct bus_attribute *bus_attr = to_bus_attr(attr);
111 struct bus_type_private *bus_priv = to_bus(kobj); - 112 ssize_t ret = 0;
113 - 114 if (bus_attr->store)
115 ret = bus_attr->store(bus_priv->bus, buf, count); - 116 return ret;
- 117}
95static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
bus_attribute结构体定义如下:[cpp] view plaincopyprint?
- 39 struct attribute attr;
40 ssize_t (*show)(struct bus_type *bus, char *buf); - 41 ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
- 42};
38struct bus_attribute {
回到bus_register函数:899行,设置priv->subsys.kobj.ktype为 &bus_ktype;回忆一下前面的文章《Linux设备模型分析之kobject》,对kobject属性的读写操作将调用kobject.ktype定义的sysfs_ops函数集指定的show和store函数。所以对bus属性文件的读写操作将会调用bus_ktyp.sysfs_ops指定的bus_attr_show和bus_attr_store函数,这两个函数我们前面已经分析过了,他们将回溯到bus_attr->show和bus_attr->store函数。900行,设置priv->drivers_autoprobe为1;902行,调用kset_register注册priv->subsys,即注册代表bus的kset。注册完成后,将在/sys/bus目录下出现对应该bus的目录。906行,调用bus_create_file(bus, &bus_attr_uevent),创建uevent属性文件,该函数定义如下:[cpp] view plaincopyprint?
- 125{
126 int error; - 127 if (bus_get(bus)) {
128 error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr); - 129 bus_put(bus);
130 } else - 131 error = -EINVAL;
132 return error; - 133}
124int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
128行,调用sysfs_create_file函数创建了bus_attribute对应的属性文件。先来看bus_attr_uevent的定义,它是通过宏BUS_ATTR生成的:[cpp] view plaincopyprint?
- 870static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
870static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
BUS_ATTR定义如下:[cpp] view plaincopyprint?
- 45struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
44#define BUS_ATTR(_name, _mode, _show, _store) \
44#define BUS_ATTR(_name, _mode, _show, _store) \45struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
__ATTR定义如下:[cpp] view plaincopyprint?
- 71 .attr = {.name = __stringify(_name), .mode = _mode }, \
72 .show = _show, \ - 73 .store = _store, \
- 74}
70#define __ATTR(_name,_mode,_show,_store) { \
70#define __ATTR(_name,_mode,_show,_store) { \71 .attr = {.name = __stringify(_name), .mode = _mode }, \72 .show = _show, \73 .store = _store, \74}
从bus_attr_uevent的定义可以看出,对应的uevent属性只有store接口,没有实现show接口。store接口函数bus_uevent_store定义如下:[cpp] view plaincopyprint?
- 862 const char *buf, size_t count)
863{ - 864 enum kobject_action action;
865 - 866 if (kobject_action_type(buf, count, &action) == 0)
867 kobject_uevent(&bus->p->subsys.kobj, action); - 868 return count;
- 869}
861static ssize_t bus_uevent_store(struct bus_type *bus,
回到bus_register函数:910 - 915行,创建名为devices的kset,其parent是priv->subsys.kobj,即在相应bus目录下创建一个devices目录。917 - 922行,创建名为drivers的kset,其parent是priv->subsys.kobj,即在相应bus目录下创建一个drivers目录。924行,初始化priv->klist_devices,即devices链表。925行,初始化priv->klist_drivers,即drivers链表。927行,调用add_probe_files(bus)函数创建drivers_probe和drivers_autoprobe两个属性文件,该函数定义如下:[cpp] view plaincopyprint?
- 607{
608 int retval; - 609
610 retval = bus_create_file(bus, &bus_attr_drivers_probe); - 611 if (retval)
612 goto out; - 613
614 retval = bus_create_file(bus, &bus_attr_drivers_autoprobe); - 615 if (retval)
616 bus_remove_file(bus, &bus_attr_drivers_probe); - 617out:
618 return retval; - 619}
606static int add_probe_files(struct bus_type *bus)
bus_create_file函数我们前面已经分析过了,610行,创建drivers_probe属性文件,614行,创建drivers_autoprobe属性文件。其对应的bus_attribute定义如下:[cpp] view plaincopyprint?
- 603static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
- 604 show_drivers_autoprobe, store_drivers_autoprobe);
602static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
602static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);603static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,604 show_drivers_autoprobe, store_drivers_autoprobe);
属性文件对应的操作函数定义如下:[cpp] view plaincopyprint?
- 226{
227 return sprintf(buf, "%d\n", bus->p->drivers_autoprobe); - 228}
229 - 230static ssize_t store_drivers_autoprobe(struct bus_type *bus,
231 const char *buf, size_t count) - 232{
233 if (buf[0] == '0') - 234 bus->p->drivers_autoprobe = 0;
235 else - 236 bus->p->drivers_autoprobe = 1;
237 return count; - 238}
239 - 240static ssize_t store_drivers_probe(struct bus_type *bus,
241 const char *buf, size_t count) - 242{
243 struct device *dev; - 244
245 dev = bus_find_device_by_name(bus, NULL, buf); - 246 if (!dev)
247 return -ENODEV; - 248 if (bus_rescan_devices_helper(dev, NULL) != 0)
249 return -EINVAL; - 250 return count;
- 251}
225static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
show_drivers_autoprobe函数用于显示bus->p->drivers_autoprobe的值。store_drivers_autoprobe函数根据用户的要求设置bus->p->drivers_autoprobe的值。store_drivers_probe函数245行调用bus_find_device_by_name 在bus上查找用户指定的device,并且在248行调用bus_rescan_devices_helper函数查找匹配device_driver.回到bus_register函数:931行,调用bus_add_attrs函数创建bus默认属性文件,该函数定义如下:[cpp] view plaincopyprint?
- 811 * bus_add_attrs - Add default attributes for this bus.
812 * @bus: Bus that has just been registered. - 813 */
814 - 815static int bus_add_attrs(struct bus_type *bus)
816{ - 817 int error = 0;
818 int i; - 819
820 if (bus->bus_attrs) { - 821 for (i = 0; attr_name(bus->bus_attrs); i++) {
822 error = bus_create_file(bus, &bus->bus_attrs);- 823 if (error)
824 goto err;- 825 }
826 }- 827done:
828 return error;- 829err:
830 while (--i >= 0)- 831 bus_remove_file(bus, &bus->bus_attrs);
832 goto done;- 833}
- 823 if (error)
810/**
820 - 826行,如果bus->bus_attrs指定了bus的默认属性,则创建对应的属性文件。
请问一下,你是怎么COPY的。可以这样显示。
我怎么每次COPY过来都是显示是普通的。并不能显示代码编写的样子。
选中,右键,复制粘贴。
这个可能跟源网页的格式有关。
你不说我都没仔细看,我当时发表的时候不是这个样子的,当时就像txt中的那样,发表完了我还看了一遍,这什么时候变成这个样子了。
中间还有乱七八糟的部分,好像是前面代码段的重复。关键是汉字描述部分,看着太难受了。