原文地址:http://blog.csdn.net/tuzhutuzhu/article/details/34445847
Linux的驱动程序注册过程,大致分为两个步骤:
- 模块初始化
- 驱动程序注册
下面以内核提供的示例代码pci-skeleton.c,详细说明一个pci设备驱动程序的注册过程。其他设备的驱动代码注册过程基本相同,大家可自行查看。使用的内核代码版本是2.6.38。
1. 模块初始化
1.1 驱动程序入口
所有的设备驱动程序都会有如下两行代码:
1.2 模块初始化
当驱动程序开始执行时,首先会执行该驱动程序的初始化函数netdrv_init_module,代码如下:
1907 {
2.1 linux总线设备驱动模型
关于总线设备驱动模型,很多书上都有详细的讲解,但是都很抽象,很难理解(至少我是这样认为的)。下面我尽量用最简单的方法来说明相关内容。
linux内核中分别用struct bus_type,struct device和struct device_driver来描述总线、设备和驱动。
总线:
51 const char *name;
52 struct bus_attribute *bus_attrs;
53 struct device_attribute *dev_attrs;
54 struct driver_attribute *drv_attrs;
55
407 struct device *parent;
上述三个结构体中,我将下文需要使用的成员进行了标识,后面会讨论到。
对比上面的三个结构体,你会发现:总线中既定义了设备,也定义了驱动;设备中既有总线,也有驱动;驱动中既有总线也有设备相关的信息。那这三个的关系到底是什么呢?
当一个struct device诞生,总线就会去driver链表找设备对应的驱动程序。如果找到就执行设备的驱动程序,否则就等待。反之亦然。
2.2 注册函数详解
下面我们来详细解释驱动的注册函数。
2.2.1 驱动的描述
首先从register函数的函数原型看起:
897 __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
1103 int __pci_register_driver( struct pci_driver *drv, struct module *owner,
1104 const char *mod_name)
543 struct list_head node;
556 };
144 unsigned int class;
首先看下实例代码中是怎么玩的:
1895 .name = MODNAME,
1896 .id_table = netdrv_pci_tbl,
1897 . probe = netdrv_init_one,
1898 . remove = __devexit_p(netdrv_remove_one),
1899 #ifdef CONFIG_PM 1900 .suspend = netdrv_suspend,
1901 .resume = netdrv_resume,
那上面的几个分别什么作用呢?
name:驱动模块的名字,这个可以忽略。
id_table:这个id的表很重要, 它的作用是匹配驱动所支持的设备。 同样看看代码中的用法:
221 static DEFINE_PCI_DEVICE_TABLE(netdrv_pci_tbl) = { 222 {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, 223 {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NETDRV_CB }, 224 {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX }, 225 /* {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/ 226 {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 }, 227 {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 }, 228 {0,} 229 }; 230 MODULE_DEVICE_TABLE(pci, netdrv_pci_tbl);这里表示的就是本驱动程序支持的设备类型。
probe:这个函数指针同样很重要。 当驱动匹配到了对应的设备之后,就会调用该函数来驱动设备。 所以可以说这个函数才是驱动程序真正的入口。
remove:当驱动程序对应的设备被删除之后,使用这个函数来删除驱动程序。
综合看来,上面的id_table和probe函数好像是最重要的,那我们就看看它们是怎么使用的。
2.2.2 驱动-设备的匹配
上面在说明probe函数的时候说到:当驱动 匹配 到了对应的设备之后,就会调用该函数来驱动设备。这个匹配是什么意思?如何进行匹配?跟bus结构体中的match函数有没有关系?
带着这几个问题,我们来看看register函数。这里我将只说明驱动-设备匹配相关的内容,过程中看到的其他内容不在讨论范围内。我们将调用过程加粗和标红。
1104 const char *mod_name)
1105 {
1106 int error;
1110 drv->driver.bus = &pci_bus_type;
1111 drv->driver.owner = owner;
1120 goto out;
1121
。。。。。。。。
1137 }
__pci_register_driver函数中,调用driver_register,在总线上注册驱动。
223 {
231 ( drv->bus->shutdown && drv->shutdown))
driver_register中调用bus_add_driver,将设备驱动添加到总线上。
626 {
。。。。。。。。。。。。。
642 klist_init(&priv->klist_devices, NULL, NULL);
643 priv->driver = drv;
644 drv->p = priv;
645 priv->kobj.kset = bus->p->drivers_kset;
646 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
647 "%s", drv->name);
648 if (error)
649 goto out_unregister;
650
651 if (drv->bus->p->drivers_autoprobe) {
304 {
286 void * data, int (* fn)( struct device *, void *))
287 {
。。。。。。。。。。。。
295 klist_iter_init_node(&bus->p->klist_devices, &i,
296 (start ? &start->p->knode_bus : NULL));
266 {
267 struct device_driver *drv = data;
288 if (dev->parent)
279行的driver_match_device函数就是用来为driver匹配device的。match函数和probe函数被调用的地方
if (!driver_match_device(drv, dev))//在驱动driver注册到总线时调用match函数。
286 driver_probe_device(drv, dev);//当驱动注册到总线并match成功后,调用驱动probe()函数
108 static inline int driver_match_device(struct device_driver *drv, 109 struct device *dev) 110 { 111 return drv->bus->match ? drv->bus->match(dev, drv) : 1; 112 }
这里开始调用device_driver中注册BUS总线上的match函数来进行匹配了,匹配的具体过程就不看了。再回到上面的__driver_attach函数的driver_probe_device中。
201 {
212 ret = really_probe(dev, drv);
109 {
110 int ret = 0;
111 112 atomic_inc(&probe_count);
113 pr_debug( "bus: '%s': %s: probing driver %s with device %s\n",
114 drv->bus->name, __func__, drv->name, dev_name(dev));
115 WARN_ON(!list_empty(&dev->devres_head));
116 117 dev->driver = drv;
118 if (driver_sysfs_add(dev)) {
119 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
120 __func__, dev_name(dev));
121 goto probe_failed;
126 if (ret)
127 goto probe_failed;
128 } else if (drv->probe) {
129 ret = drv->probe(dev);
130 if (ret)
131 goto probe_failed;
132 }
133
。。。。。。。。。。。。。。
160 }
到这里,终于看到drv->probe函数了。驱动程序的probe函数开始执行了,驱动程序的注册工作也就大功告成了。
3. 总结
我们来总结一下设备驱动程序初始化的几个步骤:
1. 根据设备类型,构造所需描述驱动的结构体。该结构体需要继承struct device_driver结构,并给几个重要的成员初始化。
2. 通过module_init宏调用驱动程序的初始化函数xx_init_module,在初始化函数中注册驱动程序。
3.驱动程序会遍历总线上的struct device和struct device_driver两条链表,调用总线的match函数,对设备与驱动程序进行匹配。