一、bus定义
Linux设备驱动模型中的bus,即可以是物理总线(如PCI、I2C总线)的抽象,也可以是出于设备驱动模型架构需要而定义的虚拟的“platform”总线。一个符合Linux设备驱动模型的device或device_driver必须挂靠在一个bus上,无论这个bus是物理的还是虚拟的。
Linux内核使用bus_type结构体来描述bus,该结构体定义在include/linux/device.h文件中,其内容如下:
- 56
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 93struct bus_type {
- 94 const char *name;
- 95 const char *dev_name;
- 96 struct device *dev_root;
- 97 struct bus_attribute *bus_attrs;
- 98 struct device_attribute *dev_attrs;
- 99 struct driver_attribute *drv_attrs;
- 100
- 101 int (*match)(struct device *dev, struct device_driver *drv);
- 102 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
- 103 int (*probe)(struct device *dev);
- 104 int (*remove)(struct device *dev);
- 105 void (*shutdown)(struct device *dev);
- 106
- 107 int (*suspend)(struct device *dev, pm_message_t state);
- 108 int (*resume)(struct device *dev);
- 109
- 110 const struct dev_pm_ops *pm;
- 111
- 112 struct iommu_ops *iommu_ops;
- 113
- 114 struct subsys_private *p;
- 115 struct lock_class_key lock_key;
- 116};
下面我们来看一下bus_type各个成员的作用:
name,代表bus的名字。
dev_name,用来遍历bus上的device。
dev_root,bus上device的根节点。
bus_attrs,bus的属性。
dev_attrs,bus上device的属性。
drv_attrs,bus上device_driver的属性。
match,当一个新的device或device driver被加入到该bus时,match函数会被调用进行匹配操作。更详细的说,当一个device被加入时,会和bus上的所有device_driver进行匹配操作,如果有device_driver能支持这个device,则匹配成功,match返回非0值。当一个device_driver被加入到bus时,会和bus上的所有device进行匹配操作,如果有它能支持的device,则匹配成功,match返回非0值。
uevent,当某个device加入或被删除,或者其它一些会发送uevnt消息的事件发生时,该函数会被调用。
probe,当一个新的device或device_driver被加入bus时,该函数会被调用,它又会进而调用相应device_driver的probe函数对匹配的device进行初始化。
remove,当一个device被删除时,这个函数会被调用。
shutdown,当系统关机时,该函数会被调用。
suspend,当bus的某个device要进入休眠状态时,这个函数会被调用。
resume,当bus上的某个休眠device被唤醒时,这个函数会被调用。
pm,bus上的电源管理操作函数,会进而调用相应device_driver的pm函数。
iommu_ops,bus的iommu相关操作。
p,bus私有数据,只有bus driver本身能访问这些数据,其类型是struct subsys_private,该结构体定义在drivers/base/base.h文件中,其内容如下:
- 3
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 28struct subsys_private {
- 29 struct kset subsys;
- 30 struct kset *devices_kset;
- 31 struct list_head interfaces;
- 32 struct mutex mutex;
- 33
- 34 struct kset *drivers_kset;
- 35 struct klist klist_devices;
- 36 struct klist klist_drivers;
- 37 struct blocking_notifier_head bus_notifier;
- 38 unsigned int drivers_autoprobe:1;
- 39 struct bus_type *bus;
- 40
- 41 struct kset glue_dirs;
- 42 struct class *class;
- 43};
subsys,代表bus对应的kset,即bus对应子系统。bus对应一个kset,而device和device_driver都对应一个kobject,由此也可以看出它们的区别。在Linux设备模型中,bus对应的kset是subsys,bus对应的kobject是subsys.kobj,bus对应的父kset是subsys.kobj.kset。所有通过bus_register注册进系统的bus的父kset均为bus_kset,它对应/sys/bus目录,所以,bus对应的目录都在/sys/bus目录下,如/sys/bus/usb。
devices_kset,该bus上所有device的集合。
interfaces,子系统interfaces链表。
drivers_kset,该bus上所有device_driver的集合。
klist_devices,该bus上所有device的链表。
klist_drivers,该bus上所有device_driver的链表。
bus_notifier,bus notifier列表。
drivers_autoprobe,表明当向bus加入一个device或device_driver时,是否自动进行匹配操作。
bus,指向相关联的bus_type。
二、bus初始化
bus的初始化操作是在buses_init函数中完成的,该函数定义在drivers/base/bus.c文件中,其内容如下:
- 1300int __init buses_init(void)
- 1301{
- 1302 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
- 1303 if (!bus_kset)
- 1304 return -ENOMEM;
- 1305
- 1306 system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
- 1307 if (!system_kset)
- 1308 return -ENOMEM;
- 1309
- 1310 return 0;
- 1311}
1302行,调用kset_create_and_add创建bus_kset,它是所有bus的容器,对应/sys/bus目录。这里指定了当bus_kset中的成员状态有变化时,用来通知用户空间的uevent操作函数集为bus_uevent_ops,它定义在drivers/base/bus.c文件中,其内容如下:
- 161static const struct kset_uevent_ops bus_uevent_ops = {
- 162 .filter = bus_uevent_filter,
- 163};
这个操作函数集中只定义了filter函数,用来决定状态发生变化时是否通知用户空间,其定义如下:
- 152static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
- 153{
- 154 struct kobj_type *ktype = get_ktype(kobj);
- 155
- 156 if (ktype == &bus_ktype)
- 157 return 1;
- 158 return 0;
- 159}
如果ktype不是“bus_ktype”,则不通知用户空间。
回到buses_init函数,1306行,调用kset_create_and_add创建system_kset,对应/sys/devices/system目录。
三、bus的注册
注册一个bus是通过调用bus_register函数完成的,该函数定义在drivers/base/bus.c文件中,其内容如下:
- 900
-
-
-
-
-
-
-
- 908int bus_register(struct bus_type *bus)
- 909{
- 910 int retval;
- 911 struct subsys_private *priv;
- 912 struct lock_class_key *key = &bus->lock_key;
- 913
- 914 priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
- 915 if (!priv)
- 916 return -ENOMEM;
- 917
- 918 priv->bus = bus;
- 919 bus->p = priv;
- 920
- 921 BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
- 922
- 923 retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
- 924 if (retval)
- 925 goto out;
- 926
- 927 priv->subsys.kobj.kset = bus_kset;
- 928 priv->subsys.kobj.ktype = &bus_ktype;
- 929 priv->drivers_autoprobe = 1;
- 930
- 931 retval = kset_register(&priv->subsys);
- 932 if (retval)
- 933 goto out;
- 934
- 935 retval = bus_create_file(bus, &bus_attr_uevent);
- 936 if (retval)
- 937 goto bus_uevent_fail;
- 938
- 939 priv->devices_kset = kset_create_and_add("devices", NULL,
- 940 &priv->subsys.kobj);
- 941 if (!priv->devices_kset) {
- 942 retval = -ENOMEM;
- 943 goto bus_devices_fail;
- 944 }
- 945
- 946 priv->drivers_kset = kset_create_and_add("drivers", NULL,
- 947 &priv->subsys.kobj);
- 948 if (!priv->drivers_kset) {
- 949 retval = -ENOMEM;
- 950 goto bus_drivers_fail;
- 951 }
- 952
- 953 INIT_LIST_HEAD(&priv->interfaces);
- 954 __mutex_init(&priv->mutex, "subsys mutex", key);
- 955 klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
- 956 klist_init(&priv->klist_drivers, NULL, NULL);
- 957
- 958 retval = add_probe_files(bus);
- 959 if (retval)
- 960 goto bus_probe_files_fail;
- 961
- 962 retval = bus_add_attrs(bus);
- 963 if (retval)
- 964 goto bus_attrs_fail;
- 965
- 966 pr_debug("bus: '%s': registered\n", bus->name);
- 967 return 0;
- 968
- 969bus_attrs_fail:
- 970 remove_probe_files(bus);
- 971bus_probe_files_fail:
- 972 kset_unregister(bus->p->drivers_kset);
- 973bus_drivers_fail:
- 974 kset_unregister(bus->p->devices_kset);
- 975bus_devices_fail:
- 976 bus_remove_file(bus, &bus_attr_uevent);
- 977bus_uevent_fail:
- 978 kset_unregister(&bus->p->subsys);
- 979out:
- 980 kfree(bus->p);
- 981 bus->p = NULL;
- 982 return retval;
- 983}
914行,为struct subsys_private指针priv分配内存空间。
923行,设置priv->subsys.kobj的名字为bus->name,对应sysfs文件系统中该bus的目录名。
927行,设置priv->subsys.kobj.kset为bus_kset,即所有通过bus_register函数注册的bus本身是一个kset(即priv->subsys),该kset对应的kobject是priv->subsys.kobj,该kset的父kset是priv->subsys.kobj.kset,这里设置为bus_kset。因为bus_kset在buses_init函数中初始化,对应/sys/bus目录,所以后面我们注册的bus的根目录都在/sys/bus目录下,如/sys/bus/usb。
928行,设置priv->subsys.kobj.ktype为bus_ktype。因为对kobject属性文件的读写操作将会调用kobject.ktype.sysfs_ops指定的show和store函数,所以,读写bus对应的属性文件,将会调用bus_ktype.sysfs_ops指定的show和store函数。bus_ktype定义在drivers/base/bus.c文件中,其内容如下:
- 148static struct kobj_type bus_ktype = {
- 149 .sysfs_ops = &bus_sysfs_ops,
- 150};
bus_sysfs_ops定义在drivers/base/bus.c文件中,其内容如下:
- 122static const struct sysfs_ops bus_sysfs_ops = {
- 123 .show = bus_attr_show,
- 124 .store = bus_attr_store,
- 125};
同样是在drivers/base/bus.c文件中,bus_attr_show和bus_attr_store函数定义如下:
- 95
-
-
- 98static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
- 99 char *buf)
- 100{
- 101 struct bus_attribute *bus_attr = to_bus_attr(attr);
- 102 struct subsys_private *subsys_priv = to_subsys_private(kobj);
- 103 ssize_t ret = 0;
- 104
- 105 if (bus_attr->show)
- 106 ret = bus_attr->show(subsys_priv->bus, buf);
- 107 return ret;
- 108}
- 109
- 110static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
- 111 const char *buf, size_t count)
- 112{
- 113 struct bus_attribute *bus_attr = to_bus_attr(attr);
- 114 struct subsys_private *subsys_priv = to_subsys_private(kobj);
- 115 ssize_t ret = 0;
- 116
- 117 if (bus_attr->store)
- 118 ret = bus_attr->store(subsys_priv->bus, buf, count);
- 119 return ret;
- 120}
to_bus_attr是一个宏,定义在drivers/base/bus.c文件中,如下:
- 26#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
bus_attribute定义在include/linux/device.h文件中,其内容如下:
- 43struct bus_attribute {
- 44 struct attribute attr;
- 45 ssize_t (*show)(struct bus_type *bus, char *buf);
- 46 ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
- 47};
to_subsys_private定义在drivers/base/base.h文件中,如下:
- 44#define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj)
至此,我们可以回顾一下整个调用流程:
调用bus_register注册任意一个bus时(如usb、i2c等等),都指定了该bus对应的bus_type.p.subsys.kobj.ktype为bus_ktype,所以对任意一个bus对应的属性文件进行读写操作时,都会调用bus_ktype.sysfs_ops.bus_attr_show和bus_ktype.sysfs_ops.bus_attr_store函数。注意,读写usb总线属性文件时是调用这两个函数,读写i2c总线属性文件时也是调用这两个函数,所有的总线调用的是同一个函数。那么怎么区分不同总线的操作呢?关键点是在bus_attr_show和bus_attr_store函数内部,通过to_bus_attr将参数传递过来的struct attribute变量转换为包含它的struct bus_attribute对象,进而调用bus_attribute.show和bus_attribute.store函数。而bus_attribute对象定义在bus_type结构体中,即bus_type.bus_attrs,每个bus有不同的bus_type定义,也就有不同的bus_type.bus_attrs,也就有不同的bus_type.bus_attrs.show和bus_type.bus_attrs.store实现。
回到bus_register函数中:
929行,设置priv->drivers_autoprobe为1,指示当向bus加入一个device或device_driver时,自动进行匹配操作。
931行,调用kset_register注册priv->subsys,这时在/sys/bus下创建了相应bus目录结构。
935行,调用bus_create_file创建bus_attr_uevent对应的属性文件。
bus_create_file函数定义在drivers/base/bus.c文件中,其内容如下:
- 127int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
- 128{
- 129 int error;
- 130 if (bus_get(bus)) {
- 131 error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
- 132 bus_put(bus);
- 133 } else
- 134 error = -EINVAL;
- 135 return error;
- 136}
bus_attr_uevent定义在drivers/base/bus.c文件中:
- 898static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
BUS_ATTR定义在include/linux/device.h文件中:
- 49#define BUS_ATTR(_name, _mode, _show, _store) \
- 50struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
__ATTR定义在include/linux/sysfs.h文件中:
- 66
-
-
-
- 70
- 71#define __ATTR(_name,_mode,_show,_store) { \
- 72 .attr = {.name = __stringify(_name), .mode = _mode }, \
- 73 .show = _show, \
- 74 .store = _store, \
- 75}
由bus_attr_uevent的定义可以看出,它没有定义show函数,而是只定义了store函数bus_uevent_store,该函数定义在drivers/base/bus.c文件中,其内容如下:
- 889static ssize_t bus_uevent_store(struct bus_type *bus,
- 890 const char *buf, size_t count)
- 891{
- 892 enum kobject_action action;
- 893
- 894 if (kobject_action_type(buf, count, &action) == 0)
- 895 kobject_uevent(&bus->p->subsys.kobj, action);
- 896 return count;
- 897}
回到bus_register函数:
939-944行,调用kset_create_and_add创建名为devices的kset,赋值给priv->devices_kset,并指定该kset的parent kobject为priv->subsys.kobj。所以该kset对应于用户空间/sys/bus/bus_name/devices目录。
946-951行,调用kset_create_and_add创建名为devices的kset,赋值给priv->drivers_kset,并指定该kset的parent kobject为priv->subsys.kobj。所以该kset对应于用户空间/sys/bus/bus_name/drivers目录。
953行,初始化priv->interfaces
955行,初始化priv->klist_devices,klist_devices_get和klist_devices_put函数定义在drivers/base/bus.c文件中,其内容如下:
- 873static void klist_devices_get(struct klist_node *n)
- 874{
- 875 struct device_private *dev_prv = to_device_private_bus(n);
- 876 struct device *dev = dev_prv->device;
- 877
- 878 get_device(dev);
- 879}
- 880
- 881static void klist_devices_put(struct klist_node *n)
- 882{
- 883 struct device_private *dev_prv = to_device_private_bus(n);
- 884 struct device *dev = dev_prv->device;
- 885
- 886 put_device(dev);
- 887}
956行,初始化priv->klist_drivers。
958行,调用add_probe_files函数,该函数定义在drivers/base/bus.c文件中,其内容如下:
- 641static int add_probe_files(struct bus_type *bus)
- 642{
- 643 int retval;
- 644
- 645 retval = bus_create_file(bus, &bus_attr_drivers_probe);
- 646 if (retval)
- 647 goto out;
- 648
- 649 retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
- 650 if (retval)
- 651 bus_remove_file(bus, &bus_attr_drivers_probe);
- 652out:
- 653 return retval;
- 654}
该函数创建了两个属性文件:/sys/bus/bus_name/drivers_probe和/sys/bus/bus_name/drivers_autoprobe
属性bus_attr_drivers_probe和bus_attr_drivers_autoprobe定义在drivers/base/bus.c文件中,如下:
- 637static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
- 638static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
- 639 show_drivers_autoprobe, store_drivers_autoprobe);
可见bus_attr_drivers_probe只定义了store函数,bus_attr_drivers_autoprobe定义了show和store两个函数,它们都定义在drivers/base/bus.c文件中,如下:
- 226static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
- 227{
- 228 return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);
- 229}
- 230
- 231static ssize_t store_drivers_autoprobe(struct bus_type *bus,
- 232 const char *buf, size_t count)
- 233{
- 234 if (buf[0] == '0')
- 235 bus->p->drivers_autoprobe = 0;
- 236 else
- 237 bus->p->drivers_autoprobe = 1;
- 238 return count;
- 239}
- 240
- 241static ssize_t store_drivers_probe(struct bus_type *bus,
- 242 const char *buf, size_t count)
- 243{
- 244 struct device *dev;
- 245
- 246 dev = bus_find_device_by_name(bus, NULL, buf);
- 247 if (!dev)
- 248 return -ENODEV;
- 249 if (bus_rescan_devices_helper(dev, NULL) != 0)
- 250 return -EINVAL;
- 251 return count;
- 252}
show_drivers_autoprobe函数只是显示当前bus->p->drivers_autoprobe的值。
store_drivers_autoprobe函数根据用户空间传递过来的参数设置bus->p->drivers_autoprobe的值。
store_drivers_probe函数在246行调用bus_find_device_by_name函数根据用户空间传递进来的设备名(保存在buf中)查找对应的device。249行,调用bus_rescan_devices_helper函数为该设备查找对应的device_driver。
回到bus_register函数:
962行,调用bus_add_attrs,该函数定义在drivers/base/bus.c文件中,其内容如下:
- 838
-
-
-
- 842
- 843static int bus_add_attrs(struct bus_type *bus)
- 844{
- 845 int error = 0;
- 846 int i;
- 847
- 848 if (bus->bus_attrs) {
- 849 for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
- 850 error = bus_create_file(bus, &bus->bus_attrs[i]);
- 851 if (error)
- 852 goto err;
- 853 }
- 854 }
- 855done:
- 856 return error;
- 857err:
- 858 while (--i >= 0)
- 859 bus_remove_file(bus, &bus->bus_attrs[i]);
- 860 goto done;
- 861}
如果指定了bus的默认属性,即bus->bus_attrs不为NULL,则创建对应的属性文件。
至此,bus_register函数我们就分析完了。