如何实现Linux设备驱动模型
Linuxlinux硬件驱动架构

Linuxlinux硬件驱动架构linux硬件驱动(usb)模块:模块用来装载到内核中,用来实现设备驱动程序。
linux对于一个硬件的驱动,使用两种方式加载: 1. 直接加载到内核代码中,启动内核时就会驱动此硬件设备 2. 以模块方式加载,编译生成一个.o的文件,当应用程序需要时加载进内核空间运行 so (通常说的硬件驱动其实就是一个硬件驱动模块及.o文件)设备文件(设备节点):设备文件(设备节点)指定(主设备号)&& (次设备号)主设备号:对应着确定的驱动程序。
(声明设备所使用的驱动程序,设备号相当于硬件驱动程序的一个标识)次设备号:区分不同属性,不同使用方法,不同位置,不同操作设备号从/proc/drives中获取,so 先有驱动程序在内核中,才有设备节点在目录中。
SCSI(并口):通常使用的的usb存储设备,是模拟scsi硬盘而进行设计的。
Linux硬件驱动架构:.o驱动模块文件--(如果需要使用这个驱动程序,首先要加载运行它)-->insmod *.o--(驱动程序根据字符设备类型或块设备类型(鼠标属于字符设备,硬盘属于块设备))向系统注册-->注册成功之后系统返回一个主设备号---(根据主设备号创建一个放置在/dev目录下的设备文件)-->(mknod 用来创建设备文件需要用到设备号这个参数)----->我们访问硬件时,就可以对设备文件通过open,read,write等命令进行,而驱动就会接收到相应的read,write 操作而根据自己模块中的相应函数进行。
上层调用api.o 驱动drive.o与模块相关的一些东西:1. /lib/modules/2.6.**目录,下面是针对当前内核版本的模块。
Linux的总线设备驱动模型

Linux的总线设备驱动模型裸机编写驱动⽐较⾃由,按照⼿册实现其功能即可,每个⼈写出来都有很⼤不同;⽽Linux中还需要按照Linux的驱动模型来编写,也就是需要按照“模板”来写,写出来的驱动就⽐较统⼀。
⼀、 Linux采⽤总线设备驱动模型。
主要包含总线、设备、驱动三个部分。
总线:最先注册,有⼏个重要的回调函数,例如match函数⽤于匹配device和driver。
设备:设备的物理信息,例如设备名、物理地址、中断号等;驱动:设备的驱动程序和设备名等信息,例如初始化函数、波特率设置函数、启动停⽌函数、中断函数等。
现实中,很多设备都是接在总线上的,例如SPI Flash接在SPI总线上,EEPROM接在I2C总线上。
但也有很多芯⽚内部设备没有挂在总线上,例如UART、SPI控制器。
为了统⼀使⽤Linux总线设备驱动模型,内核中定义了⼀个虚拟总线platform_bus_type,将这些设备(叫做平台设备)注册到该虚拟总线上统⼀管理。
⼆、Linux驱动注册顺序(总线、设备、驱动三者关系)1、注册总线 xxx_bus_type:在系统初始化阶段,会⾸先向内核注册各种常⽤的总线类型,⽐如pci, usb, spi, i2c, platform等等。
有两个重要的链表挂在bus上,⼀个是设备device链表,⼀个是驱动driver链表。
它包含的最关键的函数:match()⽤于匹配device和driver。
//例⼦:static int __init spi_init(void){int status;printk("@@ spi_init :spi_bus_type\n");buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);if (!buf) {status = -ENOMEM;goto err0;}status = bus_register(&spi_bus_type);if (status < 0)goto err1;status = class_register(&spi_master_class);if (status < 0)goto err2;return 0;err2:bus_unregister(&spi_bus_type);err1:kfree(buf);buf = NULL;err0:return status;}2、注册设备:将系统设备注册进内核的对应总线上,⼤多是调⽤xxx_device_regisger注册。
linux驱动模型

我们将详细的介绍Linux的设备驱动模型。
Linux设备驱动模型是一个相当复杂的系统,对于初学者来说真有些无从入手。
而且更加困难的是,随着新的Linux Kernel的release,Linux 的设备驱动模型总会有或大或小的变化,我们将尽量展现Linux Kernel 的这种变化。
早期的Linux内核(版本2.4之前)并没有实现一个统一的设备模型,设备节点的创建一般是mknod命令手动创建或利用devfs文件系统创建。
早期的Linux发行版一般会采用手动创建的方式预先把通常用到的节点都创建出来,而嵌入式系统则会采用devfs的方式。
起初Linux 2.6 内核还支持devfs,但从2.6.18开始,内核完全移除了devfs系统而采用的udev的方式动态的创建设备节点。
因此,新的Linux发行版都采用udev的方式管理设备节点文件。
Linux2.6设备驱动模型的基本元素是Class、Bus、Device、Driver,下面我们分别介绍各个部分。
Class 和Class Device驱动模型最基本的概念是设备及其类别,Linux中使用struct class 和struct class_device来管理不同类别的设备。
由于设备驱动模型是一个复杂的系统,我们还是从一个简单的例子开始介绍,然后在逐步展开。
其实实现设备节点的动态创建是一个很简单的事情,并不需要太多的代码。
我们修改我们的驱动初始化函数如下:#include <linux/device.h>#define DEVNAME "hello"static dev_t dev;static struct class *hello_c lass;static struct cdev *hello_cdev;static int __init hello_init(void){int error;error = alloc_chrdev_region(&dev, 0, 2, "hello");if (error){printk("hello: alloc_chardev_region failed! ");goto out;}hello_cdev = cdev_alloc();if (hello_cdev == NULL){printk("hello: alloc cdev failed! ");error = -ENOMEM;goto out_chrdev;}hello_cdev->ops = &hello_fops;hello_cdev->owner = THIS_MODULE;error = cdev_add(hello_cdev, dev, 1);if (error){printk("hello: cdev_add failed! ");goto out_cdev;}hello_class = class_create(THIS_MODULE, DEVNAME);if (IS_ERR(hello_class)){error = PTR_ERR(hello_class);goto out_chrdev;}class_device_create(hello_class, NULL, dev, NULL, DEVNAME);memset (hello_buf, 0, sizeof(hello_buf));memcpy(hello_buf, DEFAULT_MSG, sizeof(DEFAULT_MSG));printk("hello: Hello World! ");return 0;out_cdev:cdev_del(hello_cdev);out_chrdev:unregister_chrdev_region(hello_cdev->dev, 2);out:return error;}static void __exit hello_exit(void){class_device_destroy(hello_class, dev);class_destroy(hello_class);unregister_chrdev_region(hello_cdev->dev, 2);cdev_del(hello_cdev);printk("hello: Goodbye World ");}重新编译这个驱动程序,当加载这个驱动到内核中时,系统(一般是hotplug和udev系统)就会自动的创建我们指定的设备名字:/dev/hello,同时,你也可以发现在sysfs系统中添加了新的文件:/sys/class/hello/hello/。
Linux设备驱动模型与sysfs---platform总线设备驱动

Linux在2.6版本引入了设备驱动模型,设备驱动模型负责统一实现和维护一些特性,诸如:热插拔、对象生命周期、用户空间和驱动空间的交互等基础设施1.设备驱动模型基本概念设备驱动模型主要包含:类(class)、总线(bus)、设备(device)、驱动(driver),它们的本质都是内核中的几种数据结构的“实例”∙类的本质是class结构体类型,各种不同的类其实就是class的各种实例∙总线的本质是bus_type结构体类型,各种不同的总线其实就是bus_type的各种实例∙设备的本质是device结构体类型,各种不同的设备其实就是device的各种实例∙驱动的本质是device_driver结构体类型,各种不同的驱动其实就是device_driver的各种实例2.sysfs基本概念sysfs其实就是/sys目录,其主要作用就是:展示设备驱动模型中各组件的层次关系,并将各组件的本体——内核中的数据结构以文件形式呈现,方便用户层查看及操作3./sys目录结构与设备驱动模型∙/sys目录结构很好的展示了驱动设备模型,如图:∙注意:同一个设备可能在/sys中存在多个设备文件,比如一颗led的设备文件可能在/sys/bus/platform/devices/led1,同时还有一个在/sys/class/leds/led1。
虽然他们都是同一颗led的设备文件,但是他们的来源、机制、原理都是不同的,不能混为一谈4.各组件的特性与联系∙kobject:设备驱动模型各实例的最基本单元,提供一些公用型服务如:提供该实例在sysfs中的操作方法(show和store);提供在sysfs中以文件形式存在的属性,其实就是应用接口;提供各个实例的层次架构,让sysfs中弄出目录结构。
设备驱动模型中每个实例内部都会包含一个kobject∙总线、设备、驱动,这三者有着密切的联系。
在内核中,设备和驱动是分开注册的,注册设备的时候,并不需要驱动已经存在,而驱动被注册的时候,也不需要对应的设备已经被注册。
【IT专家】linux设备驱动模型

本文由我司收集整编,推荐下载,如有疑问,请与我司联系linux设备驱动模型2012/06/05 0 最早在去年的时候学习MMC/SD/SDIO的时候就接触过设备驱动模型,但是当时也整天看书也是迷迷糊糊的,因此最终也没有将这部分知识很好的整理一下。
现在再次接触到这部分知识。
也算是完成一直以来的一个想法。
把这部分知识简单的整理一下备忘。
设备驱动模型最初是为了解决设备的电源管理而产生的,但是最后发展起来之后,作用就越来越大了,特别适合设备管理。
对于linux设备驱动工程师来说,掌握设备驱动模型非常重要。
linux的设备驱动模型的底层机制主要包括:kobject,kobj_type,kset等几个结构。
这几个结构定义在include/linux/kobject.h中。
kobject代表设备驱动模型中一个基本对象。
每个kobject都对应于sysfs中的一个目录。
上层结构例如device,device_driver,bus_type都嵌入了一个kobject,这相当于面向对象程序设计机制中的继承机制。
kobject的定义如下: 60 struct kobject { 61 const char *name;/*名称*/ 62 struct list_head entry;/*用于链入所属的kset的链表*/ 63 struct kobject *parent;/*父object*/ 64 struct kset *kset;/*所属kset*/ 65 struct kobj_type *ktype;/*所属ktype*/ 66 struct sysfs_dirent *sd;/*sysfs中的目录项*/ 67 struct kref kref;/*生命周期(引用计数)管理*/ 68 unsigned int state_initialized:1;/*标记:初始化*/ 69 unsigned int state_in_sysfs:1;/*标记:在sysfs 中*/ 70 unsigned int state_add_uevent_sent:1;/*标记:已发出KOBJ_ADD uevent*/ 71 unsigned int state_remove_uevent_sent:1;/*标记:已发出的KOBJ_REMOVE uevent*/ 72 unsigned int uevent_suppress:1;/*标记:禁止发出uevent*/ 73 };kobject的基本操作: 76 int kobject_set_name(struct kobject *kobj, const char *name, ...); 77 extern int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, 78 va_list vargs); 79 80 static inline const char *kobject_name(const struct kobject *kobj) 81 { 82 return kobj- name; 83 } 84 85 extern void kobject_init(struct kobject *kobj, struct kobj_type *ktype);。
linux字符设备驱动框架流程

linux字符设备驱动框架流程Linux字符设备驱动框架流程一、引言字符设备驱动是Linux系统中的一种设备驱动类型,用于对字符设备的操作和管理。
本文将介绍Linux字符设备驱动框架的流程,包括驱动的注册、设备的初始化、文件操作接口的实现以及驱动的注销。
二、驱动的注册1. 驱动的初始化:驱动的初始化是在模块加载时进行的,通过定义init函数来进行初始化操作。
在初始化函数中,需要进行一些准备工作,如分配主设备号、创建设备类等。
2. 分配主设备号:主设备号是用来标识设备驱动的唯一标识符,通过调用函数alloc_chrdev_region来分配主设备号。
分配成功后,可以通过主设备号和次设备号来唯一标识一个设备。
3. 创建设备类:设备类用于将具有相同属性和行为的设备分为一组,通过调用函数class_create来创建设备类。
设备类的创建需要指定设备类的名字和设备的回调函数。
4. 注册字符设备驱动:注册字符设备驱动是通过调用函数cdev_init和cdev_add来实现的。
cdev_init用于初始化字符设备结构,cdev_add用于将字符设备添加到系统中。
三、设备的初始化1. 设备的创建:设备的创建是通过调用函数device_create来实现的。
设备的创建需要指定设备类、父设备、设备号和设备名。
2. 设备的初始化:设备的初始化是在设备创建后进行的,通过定义probe函数来进行初始化操作。
在probe函数中,需要进行一些设备的特定初始化工作,如申请资源、初始化设备寄存器等。
四、文件操作接口的实现1. 文件操作接口的定义:文件操作接口是用于对设备进行读写操作的接口,包括打开设备、关闭设备、读取设备和写入设备等操作。
文件操作接口需要定义在字符设备结构的file_operations成员中。
2. 文件操作接口的实现:文件操作接口的实现是通过定义对应的函数来实现的。
在函数中,需要进行一些设备操作的具体实现,如读取设备数据、写入设备数据等。
设备驱动模型实验报告(3篇)

第1篇实验目的1. 理解Linux设备驱动模型的基本概念和结构。
2. 掌握设备驱动模型中总线、设备和驱动的交互方式。
3. 学习如何编写简单的字符设备驱动程序。
4. 熟悉Linux内核中与设备驱动模型相关的系统目录和文件。
实验环境- 操作系统:Linux- 编译器:GCC- 内核版本:Linux内核4.19- 开发工具:Makefile、内核模块编译脚本实验内容本实验主要围绕Linux设备驱动模型展开,通过实际编写一个简单的字符设备驱动程序来加深对设备驱动模型的理解。
一、实验原理Linux设备驱动模型是一种分层结构,主要包括以下几层:1. 硬件层:包括各种硬件设备。
2. 总线层:负责管理硬件设备和驱动程序之间的通信。
3. 设备层:包括各种物理设备,如硬盘、网络接口卡等。
4. 驱动层:负责与硬件设备交互,实现设备的初始化、操作等功能。
5. 用户层:通过系统调用与驱动程序交互,实现对硬件设备的操作。
在设备驱动模型中,总线、设备和驱动之间通过以下方式交互:1. 总线注册:驱动程序在初始化时,需要将自身注册到对应的总线上。
2. 设备绑定:驱动程序通过总线找到对应的设备,并将自身绑定到设备上。
3. 设备操作:用户通过系统调用与设备交互,驱动程序负责实现这些操作。
二、实验步骤1. 创建字符设备驱动程序:- 定义字符设备结构体`char_device`,包含设备名称、设备号等信息。
- 实现字符设备初始化函数`char_device_init`,负责初始化字符设备。
- 实现字符设备打开函数`char_device_open`,负责打开字符设备。
- 实现字符设备读写函数`char_device_read`和`char_device_write`,负责读写字符设备数据。
- 实现字符设备关闭函数`char_device_close`,负责关闭字符设备。
2. 注册字符设备驱动程序:- 在`init_module`函数中,注册字符设备驱动程序,包括设备名称、主设备号、次设备号等信息。
Linux设备驱动模型

Linux设备驱动模型Udev先前所需的硬件文件节点都需要在/dev下静态创建,随2.4核而来的devfs,带来了动态设备节点创建。
Devfs虽然提供了in-memory filesystem创建节点的方法,但是节点命名依然取决于设备驱动。
命名管理和内核 Udev依赖于以下技术:(1)、内核sysfs支持,sysfs启动时挂载到/sys下(可查看/etc/fstab);(2)、一系列用户空间工具:udevd和udevinfo;(3)、定义在/etc/udev/rules.d/目录下的用户定义规则使用Udev:1、首先从sysfs的相关文件中获取文件属性。
假设DVD:/dev/sr0,CD-RW:/dev/sr1。
使用udevinfo来收集设备信息。
bash> udevinfo -a -p /sys/block/sr0Code View:bash> udevinfo -a -p /sys/block/sr0...looking at the device chain at'/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4':BUS=?usb?ID=?1-4?SYSFS{bConfigurationValue}=?1?...SYSFS{idProduct}=?0701?SYSFS{idVendor}=?05e3?SYSFS{manufacturer}=?Genesyslogic?SYSFS{maxchild}=?0?SYSFS{product}=?USB Mass Storage Device?...bash> udevinfo -a -p /sys/block/sr1...looking at the device chain at'/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-3':BUS=?usb?ID=?1-3?SYSFS{bConfigurationValue}=?2?...SYSFS{idProduct}=?0302?SYSFS{idVendor}=?0dbf?SYSFS{manufacturer}=?Addonics?SYSFS{maxchild}=?0?SYSFS{product}=?USB to IDE Cable?...2、使用收集的产品信息来辨别设备并加入udev命名规则,创建一个/etc/udev/rules.d/40-cdvd.rules并加入如下规则:BUS="usb", SYSFS{idProduct}="0701", SYSFS{idVendor}="05e3",KERNEL="sr[0-9]*", NAME="%k", SYMLINK="usbdvd"BUS="usb", SYSFS{idProduct}="0302", SYSFS{idVendor}="0dbf",KERNEL="sr[0-9]*", NAME="%k", SYMLINK="usbcdrw"规则1的意思是:无论何时它发现一个产品id为0x0701,vender ID是0x05e3,而且名字以sr开头的usb设备,都会在/dev下创建一个同名的节点,并produce一个命名为usbdvd的符号链接给那个节点。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
文库资料©2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd.如何实现Linux 设备驱动模型设备驱动模型,对系统的所有设备和驱动进行了抽象,形成了复杂的设备树型结构,采用面向对象的方法,抽象出了device 设备、driver 驱动、bus 总线和class 类等概念,所有已经注册的设备和驱动都挂在总线上,总线来完成设备和驱动之间的匹配。
总线、设备、驱动以及类之间的关系错综复杂,在Linux 内核中通过kobject 、kset 和subsys 来进行管理,驱动编写可以忽略这些管理机制的具体实现。
设备驱动模型的内部结构还在不停的发生改变,如device 、driver 、bus 等数据结构在不同版本都有差异,但是基于设备驱动模型编程的结构基本还是统一的。
Linux 设备驱动模型是Linux 驱动编程的高级内容,这一节只对device 、driver 等这些基本概念作介绍,便于阅读和理解内核中的代码。
实际上,具体驱动也不会孤立的使用这些概念,这些概念都融合在更高层的驱动子系统中。
对于大多数读者可以忽略这一节内容。
1.1.1 设备在Linux 设备驱动模型中,底层用device 结构来描述所管理的设备。
device 结构在文件<linux/device.h>中定义,如程序清单错误!文档中没有指定样式的文字。
.1所示。
程序清单错误!文档中没有指定样式的文字。
.1 device 数据结构定义struct device {struct device *parent; /* 父设备*/ struct device_private *p; /* 设备的私有数据 */ struct kobjectkobj; /* 设备的kobject 对象 */ const char *init_name; /*设备的初始名字 */ struct device_type *type;/* 设备类型*/ struct mutex mutex; /*同步驱动的互斥信号量 */ struct bus_type *bus; /*设备所在的总线类型 */ struct device_driver *driver; /*管理该设备的驱动程序*/ void*platform_data;/*平台相关的数据 */ struct dev_pm_infopower;/* 电源管理*/#ifdef CONFIG_NUMA int numa_node; /*设备接近的非一致性存储结构*/ #endifu64 *dma_mask; /* DMA 掩码*/ u64 coherent_dma_mask; /*设备一致性的DMA 掩码*/struct device_dma_parameters *dma_parms; /* DMA 参数*/ struct list_headdma_pools; /* DMA 缓冲池*/ struct dma_coherent_mem*dma_mem; /* DMA 一致性内存 */ /*体系结构相关的附加项*/ struct dev_archdata archdata;/* 体系结构相关的数据*/ #ifdef CONFIG_OF文库资料©2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd.注册和注销device 的函数分别是device_register()和device_unregister(),函数原型如下:int __must_check device_register(struct device *dev); void device_unregister(struct device *dev);大多数不会在驱动中单独使用device 结构,而是将device 结构嵌入到更高层的描述结构中。
例如,内核中用spi_device 来描述SPI 设备,spi_device 结构在<linux/spi/spi.h>文件中定义,是一个嵌入了device 结构的更高层的结构体,如程序清单错误!文档中没有指定样式的文字。
.2所示。
程序清单错误!文档中没有指定样式的文字。
.2 spi_device 数据结构struct spi_device {struct device dev;/* device 数据结构*/struct spi_master *master; u32 max_speed_hz; u8 chip_select; u8 mode; u8 bits_per_word; int irq;void *controller_state; void *controller_data; char modalias[SPI_NAME_SIZE];};系统提供了device_create()函数用于在sysfs/classs 中创建dev 文件,以供用户空间使用。
device_create()函数定义如下:struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);说明:● cls 是指向将要被注册的class 结构; ● parent 是设备的父指针; ● devt 是设备的设备编号;● drvdata 是被添加到设备回调的数据; ● fmt 是设备的名字。
文库资料©2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd.与device_create()函数相反的是device_destroy()函数,用于销毁sysfs/class 目录中的dev 文件。
device_destroy()函数原型如下:void device_destroy(struct class *cls, dev_t devt);1.1.2 驱动与设备相对应,Linux 设备驱动模型中,对管理的驱动也用device_driver 结构来描述,在<linux/device.h>中定义,如程序清单错误!文档中没有指定样式的文字。
.3所示。
程序清单错误!文档中没有指定样式的文字。
.3device_driver 结构定义struct device_driver {const char *name; /* 驱动的名称*/ struct bus_type *bus; /* 驱动所在的总线 */ struct module*owner;/* 驱动的所属模块*/ const char *mod_name; /*模块名称(静态编译的时候使用) */ bool suppress_bind_attrs;/*通过sysfs 禁止bind 或者unbind */ #if defined(CONFIG_OF)const struct of_device_id *of_match_table; /* 匹配设备的表 */ #endifint (*probe) (struct device *dev);/* probe 探测方法 */ int (*remove) (struct device *dev); /* remove 方法 */ void (*shutdown) (struct device *dev); /* shutdown 方法 */ int (*suspend) (struct device *dev, pm_message_t state);/* suspend 方法 */ int (*resume) (struct device *dev);/* resume 方法*/const struct attribute_group **groups; const struct dev_pm_ops *pm; /* 电源管理 */ struct driver_private *p;/* 驱动的私有数据*/};系统提供了driver_register()和driver_ungister()分别用于注册和注销device_driver ,函数原型分别如下:int __must_check driver_register(struct device_driver *drv); void driver_unregister(struct device_driver *drv);与device 结构类似,在驱动中一般也不会单独使用device_driver 结构,通常也是嵌入在更高层的描述结构中。
还是以SPI 为例,SPI 设备的驱动结构为spi_driver ,在<linux/spi/spi.h>文件中定义,是一个内嵌了device_driver 结构的更高层的结构体,原型如程序清单错误!文档中没有指定样式的文字。
.4所示。
程序清单错误!文档中没有指定样式的文字。
.4 spi_driver 数据结构struct spi_driver {const struct spi_device_id *id_table;int (*probe)(struct spi_device *spi);int(*remove)(struct spi_device *spi);文库资料©2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd.1.1.3 总线在设备驱动模型中,所有的设备都通过总线相连,总线既可以是实际的物理总线,也可以是内核虚拟的platform 总线。
驱动也挂在总线上,总线是设备和驱动之间的媒介,为它们提供服务。
当设备插入系统,总线将在所注册的驱动中寻找匹配的驱动,当驱动插入系统中,总线也会在所注册的设备中寻找匹配的设备。
在Linux 设备驱动模型中,总线用bus_type 结构来描述。
bus_type 结构在<linux/device.h>中定义,如程序清单错误!文档中没有指定样式的文字。
.5所示。
程序清单错误!文档中没有指定样式的文字。
.5bus_type 结构定义struct bus_type {const char *name;/* 总线名称 */ struct bus_attribute *bus_attrs; /* 总线属性 */ struct device_attribute *dev_attrs; /* 设备属性 */ struct driver_attribute *drv_attrs;/* 驱动属性*/int (*match)(struct device *dev, struct device_driver *drv); /* match 方法:匹配设备和驱动 */int (*uevent)(struct device *dev, struct kobj_uevent_env *env); /* uevent 方法,支持热插拔*/ int (*probe)(struct device *dev);/* probe 方法*/ int (*remove)(struct device *dev); /* remove 方法 */ void (*shutdown)(struct device *dev); /* shutdown 方法 * int (*suspend)(struct device *dev, pm_message_t state);/* suspend 方法 */ int (*resume)(struct device *dev); /* resume 方法*/const struct dev_pm_ops *pm; /* 电源管理*/ struct bus_type_private *p;/* 总线的私有数据结构*/};说明一下bus 总线的match 方法。