Linux设备模型分析之bus
前面我们分析了Linux设备模型中kobject、kset以及ktype的使用,它们是设备模型的最基础部分,在其上有更高级一层的bus、device和driver。在这一篇文章中,我们来看一下bus的用法。
一、相关数据结构
首先,我们列出本文涉及的相关数据结构。
- 51struct bus_type {
- 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};
二、注册bus
bus的注册接口为bus_register,该函数代码如下:
- 872/**
- 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}
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行有如下定义:
- 162static struct kset *bus_kset;
同时,在buses_init函数中对bus_kset进行了初始化:
- 1054int __init buses_init(void)
- 1055{
- 1056 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
- 1057 if (!bus_kset)
- 1058 return -ENOMEM;
- 1059 return 0;
- 1060}
1056行,创建一个名为bus的kset,赋值给bus_kset,对应/sys/bus目录。所有的bus都属性bus_set,即所有的bus对应的sys系统目录都放在/sys/bus目录下。
bus_kset对应的kset_uevent_ops是bus_uevent_ops,其定义如下:
- 158static const struct kset_uevent_ops bus_uevent_ops = {
- 159 .filter = bus_uevent_filter,
- 160};
bus_uevent_filter函数定义如下:
- 149static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
- 150{
- 151 struct kobj_type *ktype = get_ktype(kobj);
- 152
- 153 if (ktype == &bus_ktype)
- 154 return 1;
- 155 return 0;
- 156}
回忆一下上一篇博客《Linux设备模型分析之kset》介绍的内容,如果kset_uevent_ops.filter函数返回0,将不会处理uevent事件。在bus_uevent_filter函数中,如果kobj->ktype不是bus_ktype,则返回0,即不处理Uevent事件。
bus_ktype定义如下:
- 145static struct kobj_type bus_ktype = {
- 146 .sysfs_ops = &bus_sysfs_ops,
- 147};
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函数定义如下:
- 95static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
- 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}
bus_attribute结构体定义如下:
- 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};
回到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属性文件,该函数定义如下:
- 124int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
- 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}
128行,调用sysfs_create_file函数创建了bus_attribute对应的属性文件。
先来看bus_attr_uevent的定义,它是通过宏BUS_ATTR生成的:
- 870static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
BUS_ATTR定义如下:
- 44#define BUS_ATTR(_name, _mode, _show, _store) \
- 45struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
__ATTR定义如下:
- 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定义如下:
- 861static ssize_t bus_uevent_store(struct bus_type *bus,
- 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}
回到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两个属性文件,该函数定义如下:
- 606static int add_probe_files(struct bus_type *bus)
- 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}
bus_create_file函数我们前面已经分析过了,610行,创建drivers_probe属性文件,614行,创建drivers_autoprobe属性文件。其对应的bus_attribute定义如下:
- 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);
属性文件对应的操作函数定义如下:
- 225static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
- 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}
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默认属性文件,该函数定义如下:
- 810/**
- 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]); i++) {
- 822 error = bus_create_file(bus, &bus->bus_attrs[i]);
- 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[i]);
- 832 goto done;
- 833}
820 - 826行,如果bus->bus_attrs指定了bus的默认属性,则创建对应的属性文件。
Linux设备模型分析之bus相关推荐
- Linux设备模型分析之kobject(基于3.10.1内核)
一.kobject结构定义 kobject是Linux设备模型的最底层数据结构,它代表一个内核对象. kobject结构体定义在include/linux/kobject.h文件中: [cpp] vi ...
- Linux设备模型分析之kobject
一.kobject应用举例 Linux设备模型最基本的组成元素是kobject,我们先来看一个kobject的应用例子,该程序在Ubuntu 10.10, 2.6.32-38-generic-pae内 ...
- Linux设备模型分析之kset
上一篇博客我们分析了Linux设备模型中kobject的注册和使用,在这一篇文章中,我们来看一下kset的用法. 首先我们看一个使用kset的例子,代码如下: [cpp] view plaincopy ...
- linux kset subsystem 3.10内核,Linux设备模型分析之kset(基于3.10.1内核)
作者:刘昊昱 内核版本:3.10.1 一.kset结构定义 kset结构体定义在include/linux/kobject.h文件中,其内容如下: 142/** 143 * struct kset - ...
- Linux设备模型分析之kset(基于3.10.1内核)
一.kset结构定义 kset结构体定义在include/linux/kobject.h文件中,其内容如下: [cpp] view plaincopy 142/** 143 * struct kset ...
- Linux通常把设备对象抽象为,linux 设备模型(1)
设备模型(一) 一.概述 从2.6内核引入了sysfs文件系统,与proc, devfs, devpty同类别,属于虚拟的文件系统.目的是展示设备驱动模型中各组件的层次关系,第一层目录:block, ...
- linux的层次结构模型,linux 设备模型(1)
设备模型(一) 一.概述 从2.6内核引入了sysfs文件系统,与proc, devfs, devpty同类别,属于虚拟的文件系统.目的是展示设备驱动模型中各组件的层次关系,第一层目录:block, ...
- Linux设备模型_导航篇
Linux设备模型_导航篇 1. Linux设备模型系列文章说明 2. Linux设备模型系列文章目录 2.0 [Linux内核的整体架构](https://zhuanlan.zhihu.com/p/ ...
- linux设备模型:bus概念及pci_bus分析
上一篇<<linux设备模型:kset及设备驱动抽象类(class)分析>>中分析了kset容器.class设备驱动抽象框架.class_kset用于类(class)的热插拔事 ...
- linux设备模型之kset/kobj/ktype分析
1. 概述 今天来聊一下Linux设备模型的基石:kset/kobject/ktype. sysfs文件系统提供了一种用户与内核数据结构进行交互的方式,可以通过mount -t sysfs sysfs ...
最新文章
- 4-1 ADO.NET简介
- webkit qt版快速编译 支持wml版本
- 【存储知识学习】第三章磁盘原理与技术3.4硬盘接口技术和SCSI硬盘接口--《大话存储》阅读笔记
- docusign文档打不开_怎样查看 docusign pdf 电子签名
- git工作中常用命令
- HISI3536安装交叉编译工具链
- python学习第七天--文件系统常用模块os,os.path,pickle
- 早教机器人刷固件_父母不要再盲目去买智能儿童早教机器人,知道这几点事半功倍!...
- win10 vs2010安装教程(超详细,附下载链接)
- EditPlus中文绿色破解版
- 英特尔it服务器芯片,intel服务器芯片组驱动程序
- 关键字Wait Until Keyword Succeeds
- 基于FPGA的卷积神经网络加速器(绪论)
- 格律诗的基本知识【一小时学会写格律诗】
- 万字总结,行业分析到底应该怎么做!
- 【吐槽大会】互联网大厂秋招版
- 活动图(Activity Diagram)—UML图(四)
- 预备作业:有关技能以及“做中学”
- Java函数式编程(基础):第一部分
- AIX系统管理(一)
热门文章
- Github Actions生成 secrets
- 山寨AR手游频出,VRAR正打造一庞大…
- Pycharm使用技巧:Split Vertically/Horizontally(垂直/水平拆分窗口)
- P5208-[WC2019] I 君的商店【交互,二分】
- Unity中游戏的存档与读档
- FineReport 11.0 帆软报表 授权文件 补丁
- 揭秘中国球员十大豪宅
- [转]Cookie详解
- Android 使用讯飞语音SDK
- 远程控制android盒子,电视盒子ADB教程 通过ADB远程安装应用方法(2)