在bus总线对应的数据结构bus_type中,有两份重要的结构体,struct kset drivers和struct kset devices。在写驱动程序的时候,要想驱动程序能工作,首先就要把驱动程序对应的driver程序放进struct kset driver结构体中,然后把设备的信息放入struct kset device中。

而pci_register_driver()就是把某个设备下的driver程序放入struct kset drivers结构体中,而这个过程又分成如下子过程:1,首先会调用int _pci_register_driver()函数,在这个函数里面,首先会把pci_driver存储的信息复制到device_driver中,因为内核最终要注册的是一个device的driver信息,而不单单指pci设备的driver信息。在复制完成之后,内核会调用driver_register()函数注册device_driver的信息,代码如下:linux/drivers/pci/pci_driver.c
/*** __pci_register_driver - register a new pci driver* @drv: the driver structure to register* @owner: owner module of drv* @mod_name: module name string* * Adds the driver structure to the list of registered drivers.* Returns a negative value on error, otherwise 0. * If no error occurred, the driver remains registered even if * no device was claimed during registration.*/
int __pci_register_driver(struct pci_driver *drv, struct module *owner,const char *mod_name)
{int error;/* initialize common driver fields */drv->driver.name = drv->name; /* struct driver is in /include/linux/device.h */drv->driver.bus = &pci_bus_type;drv->driver.owner = owner;drv->driver.mod_name = mod_name;spin_lock_init(&drv->dynids.lock);INIT_LIST_HEAD(&drv->dynids.list);/* register with core */error = driver_register(&drv->driver); /* driver/base/driver.c */

2,driver_register()函数,driver_register首先会检查struct kset drivers链表中有没有对应名称的dirver: driver_find(drv->name, drv->bus); 如果已经有了,则重新把对应的driver加载到struct kset drivers中,如果没有,则会执行bus_add_drivers函数,把当前的驱动加载到struct kset drivers中,对应程序如下:
/linux/drivers/base/drivers.c

/*** driver_register - register driver with bus* @drv: driver to register** We pass off most of the work to the bus_add_driver() call,* since most of the things we have to do deal with the bus* structures.*/
int driver_register(struct device_driver *drv)
{int ret;struct device_driver *other;BUG_ON(!drv->bus->p);if ((drv->bus->probe && drv->probe) ||(drv->bus->remove && drv->remove) ||(drv->bus->shutdown && drv->shutdown))printk(KERN_WARNING "Driver '%s' needs updating - please use ""bus_type methods\n", drv->name);other = driver_find(drv->name, drv->bus);if (other) {put_driver(other);printk(KERN_ERR "Error: Driver '%s' is already registered, ""aborting...\n", drv->name);return -EBUSY;}ret = bus_add_driver(drv); /* driver/base/bus.c */

4,bus_add_driver函数,这个函数中重要的一个操作就是driver_attach操作,在driver_attach函数中会调用dirver_match_deivce函数来判断总线上是否有设备与当前driver相匹配,实现的方式应该就是比较vendor_id和device_id。如果当前bus中有设备和当前driver相匹配,那么就会执行driver_pobe_device函数,对当前deivce进行初始化,这个probe函数就是最终指向的驱动程序中编写的probe函数,程序如下:

static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;

/** Lock device and try to bind to it. We drop the error* here and always return 0, because we need to keep trying* to bind to devices and some drivers will return an error* simply if it didn't support the device.** driver_probe_device() will spit a warning if there* is an error.*/if (!driver_match_device(drv, dev))return 0;if (dev->parent)   /* Needed for USB */down(&dev->parent->sem);
down(&dev->sem);
if (!dev->driver)driver_probe_device(drv, dev);
up(&dev->sem);
if (dev->parent)up(&dev->parent->sem);return 0;

}

至此,driver和deivce就绑定完毕,而且device也已经初始化完毕。

pci_register_driver相关推荐

  1. Linux那些事儿 之 戏说USB(24)设备的生命线(七)

    算是进入了HCD的片儿区,这里的老大不是帮派头目也不是巡逻片儿警,而是几个结构.在HCD这个片儿区,这个山头儿,王中之王就是include/linux/usb/hcd.h里定义的struct usb_ ...

  2. 2.6内核中被废弃的pci_present()

    在pci驱动是使用pci_present()函数在init函数中,编译过程中报错. 其中的源码为: static int __init shao_init(void) { int init_ret; ...

  3. Kernel PCI总线框架

    2019独角兽企业重金招聘Python工程师标准>>>     1,PCI总线介绍 在PC时代的早期,外部设备通过ISA总线接入计算机.ISA总线只有24根地址线,因此其上的外部设备 ...

  4. Linux2.6内核PCI驱动程序开发

    一,PCI相关数据结构说明 1.1struct pci_driver 这个数据结构在文件/linux/pci.h里,这是Linux内核版本2.4之后为新型的PCI设备驱动程序所添加的,其中最主要的是用 ...

  5. linux驱动 pcie 框架_Linux PCI 设备驱动基本框架(二)

    针对相应设备定义描述该PCI设备的数据结构: structdevice_private {/*注册字符驱动和发现PCI设备的时候使用*/ struct pci_dev *my_pdev;// stru ...

  6. 精彩---rtl8139网卡驱动程序分析

    学习应该是一个先把问题简单化,再把问题复杂化的过程.一开始就着手处理复杂的问题,难免让人有心惊胆颤,捉襟见肘的感觉.读Linux网卡驱动 也是一样.那长长的源码夹杂着那些我们陌生的变量和符号,望而生畏 ...

  7. Linux内核网络设备驱动

    本文首先从宏观上介绍数据包的接收过程,然后详细介绍了Linux网络设备驱动的工作过程,最后介绍网卡监控与调优,包括网络数据包总数.丢包.错包数量的相关统计. 1. 接收数据包过程概述 介绍数据包收包过 ...

  8. linux设备驱动之USB主机控制器驱动分析

    http://www.cnblogs.com/sdphome/archive/2011/09/29/2195791.html 一:前言 Usb是一个很复杂的系统.在usb2.0规范中,将其定义成了一个 ...

  9. 《Linux总线、设备与驱动》USB设备发现机制

    http://blog.csdn.net/tankai19880619/article/details/11639185 说明:本分析基于mstar801平台Linux2.6.35.11内核,其他内核 ...

  10. linux内核网络协议栈--监控和调优:接收数据(十五)

    译者序 本文翻译自 2016 年的一篇英文博客 Monitoring and Tuning the Linux Networking Stack: Receiving Data.如果能看懂英文,建议阅 ...

最新文章

  1. 2019北京高考分数分布一览表(成绩分布统计)
  2. 【线上分享】基于人眼主观视觉的画质评价与提升
  3. 软件测试团队分为哪些人员,产品团队、开发团队和测试团队是什么关系?
  4. asynchttpclient 超时_dnf这才是混子的毕业套装,却发现超时空漩涡不买账!
  5. 1415C. Bouncing Ball
  6. 编程入门到进大厂,分享一点学习经验
  7. [转]虚函数实现原理
  8. 计算机word表格转换,怎么把Word表格转换成Excel表格
  9. UI设计师不可不知的安卓屏幕知识
  10. tp6 workerman
  11. 100---Python绘制圆锥体
  12. 关于手机app合并m3u8文件失效,pc端合成方法
  13. 后端给base64码,在前端显示成图片
  14. mysql笔记整理2(聚合函数).md
  15. Springboot+vue 社团管理系统(前后端分离)
  16. malic-2021年寒假热身-05 D - 楼高莫近危阑倚(DFS+树状数组)
  17. 全新升级达内java高级互联网架构课|课件齐全
  18. 马尔科夫链预测,Python实现
  19. 汇总阿里云GPU云服务器常见问题解答FAQ
  20. python分析股票MACD指标

热门文章

  1. Spring框架基础(中)
  2. 项目1在线交流平台-7.构建安全高效的企业服务-5.redis高级数据结构应用-统计网站数据-独立访客和日活跃用户
  3. arduino硬件虚拟键盘中对应键盘上的按键整理
  4. IDEA 设置前进,后退快捷键
  5. mysql 查询活跃人数_查询活跃用户的数量SQL
  6. Nginx报错:nginx: [error] invalid PID number in /run/nginx.pid 解决方法
  7. list(map(tokenizer.tokenize, text))
  8. java 爬虫 微博_最新新浪微博爬虫程序Java版 2015
  9. 编解码学习笔记(九):QuickTime系列
  10. 编程之路之数据库(十)- PDO详解