|
【好文推荐】
Linux文件系统详解
一文透彻了解缺页异常
ARM架构处理器解析【最全的一篇!】
Linux内核操作系统: 内存映射(图文详解)!
代码大佬的【Linux内核开发笔记】分享,前人栽树后人乘凉!
Linux的驱动程序注册过程,大致分为两个步骤:
下面以内核提供的示例代码pci-skeleton.c,详细说明一个pci设备驱动程序的注册过程。其他设备的驱动代码注册过程基本相同,大家可自行查看。使用的内核代码版本是2.6.38。
1. 模块初始化
1.1 驱动程序入口
所有的设备驱动程序都会有如下两行代码:
1922 module_init(netdrv_init_module);
1923 module_exit(netdrv_cleanup_module);module_init/module_exit是两个宏。module_init是该驱动程序的入口,加载驱动模块时,驱动程序就从netdrv_init_module函数开始执行。而当该驱动程序对应的设备被删除了,则会执行netdrv_cleanup_module这个函数。
1.2 模块初始化
当驱动程序开始执行时,首先会执行该驱动程序的初始化函数netdrv_init_module,代码如下:
1906 static int __init netdrv_init_module(void)
1907 {
1908 /* when a module, this is printed whether or not devices are found in probe */
1909 #ifdef MODULE
1910 printk(version);
1911 #endif
1912 return pci_register_driver(&netdrv_pci_driver);
1913 }可以看到,初始化函数很简单,只执行了一个pci_register_driver函数就返回了。
其实模块的初始化过程就是这么简单,这也是linux驱动程序的ISO标准流程:module_init-->xx_init_module-->xx_register_driver。相信你看着这里时,还是一头雾水。别着急,我们慢慢来。
2. 驱动程序注册
什么是驱动模块的注册?上面讲到的初始化函数中调用的pci_register_driver函数就是注册驱动程序啦。在介绍注册函数之前,必须要详细说明下linux的总线设备驱动模型,否则下面的内容很难描述清楚。
2.1 linux总线设备驱动模型
关于总线设备驱动模型,很多书上都有详细的讲解,但是都很抽象,很难理解(至少我是这样认为的)。下面我尽量用最简单的方法来说明相关内容。
linux内核中分别用struct bus_type,struct device和struct device_driver来描述总线、设备和驱动。
总线:
50 struct bus_type {
51 const char *name;
52 struct bus_attribute *bus_attrs;
53 struct device_attribute *dev_attrs;
54 struct driver_attribute *drv_attrs;
55
56 <strong><span style=&#34;color:#ff0000;&#34;>int (*match)(struct device *dev, struct device_driver *drv);</span></strong>
。。。
68 };设备:
406 struct 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
<strong><span style=&#34;color:#ff0000;&#34;>419 struct bus_type *bus; /* type of bus device is on */
420 struct device_driver *driver; /* which driver has allocated this
421 device */</span></strong>
。。。
456
457 void (*release)(struct device *dev);
458 };驱动:
122 struct device_driver {
123 const char *name;
<strong><span style=&#34;color:#ff0000;&#34;>124 struct bus_type *bus;</span></strong>
125
126 struct module *owner;
127 const char *mod_name; /* used for built-in modules */
128
129 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
130
131 #if defined(CONFIG_OF)
132 const struct of_device_id *of_match_table;
133 #endif
134
<strong><span style=&#34;color:#ff0000;&#34;>135 int (*probe) (struct device *dev);</span></strong>
136 int (*remove) (struct device *dev);
。。。
145 };上述三个结构体中,我将下文需要使用的成员进行了标识,后面会讨论到。
对比上面的三个结构体,你会发现:总线中既定义了设备,也定义了驱动;设备中既有总线,也有驱动;驱动中既有总线也有设备相关的信息。那这三个的关系到底是什么呢?
三者的关系是:
内核要求每次出现一个设备,就要向总线汇报,会着说注册;每次出现一个驱动,也要向总线汇报,或者叫注册。比如系统初始化时,会扫描连接了哪些设备,并为每一个设备建立一个struct device变量,并为每一个驱动程序准备一个struct device_driver结构的变量。把这些量变量加入相应的链表,形成一条设备链表和一条驱动量表。这样,总线就能通过总线找到每一个设备和每一个驱动程序。
当一个struct device诞生,总线就会去driver链表找设备对应的驱动程序。如果找到就执行设备的驱动程序,否则就等待。反之亦然。
还有一个需要注意的地方:
usb_type结构体的match函数,它的两个参数一个是驱动,另一个则是设备。这个函数就是用来进行判断,总线上的驱动程序能不能处理设备的。至于这个函数什么时候调用,怎么调用,后面会有说。
2.2 注册函数详解
下面我们来详细解释驱动的注册函数。
2.2.1 驱动的描述
首先从register函数的函数原型看起:
896 #define pci_register_driver(driver) \
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)真正的注册函数式__pci_register_driver(),它的第一个参数是struct pci_driver类型的,再看看这个结构的定义:
542 struct pci_driver {
543 struct list_head node;
544 const char *name;
545 const struct pci_device_id *id_table; /* must be non-NULL for probe to be calle d */
546 int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New de vice inserted */
547 void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
548 int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended * /
549 int (*suspend_late) (struct pci_dev *dev, pm_message_t state);
550 int (*resume_early) (struct pci_dev *dev);
551 int (*resume) (struct pci_dev *dev); /* Device woken up */
552 void (*shutdown) (struct pci_dev *dev);
553 struct pci_error_handlers *err_handler;
<strong><span style=&#34;color:#ff0000;&#34;>554 struct device_driver driver;</span></strong>
555 struct pci_dynids dynids;
556 };仔细看这个结构,发现其中一个成员是我们上面的总线设备模型中的driver的结构体。 其实在linux内核中,所有设备的驱动的定义,都是以struct device_driver为基类,进行继承与扩展的。 你没有看错,内核当中使用了很多OO的思想。再看看网卡I2C设备的的驱动描述:
143 struct i2c_driver {
144 unsigned int class;
145
。。。
<strong><span style=&#34;color:#ff0000;&#34;>174 struct device_driver driver;</span></strong>
175 const struct i2c_device_id *id_table;
176
177 /* Device detection callback for automatic device creation */
178 int (*detect)(struct i2c_client *, struct i2c_board_info *);
179 const unsigned short *address_list;
180 struct list_head clients;
181 };现在我们知道了pci设备的驱动程序的描述方法。但是问题又来了:这么复杂的一个结构体,我们怎么用呢?
首先看下实例代码中是怎么玩的:
1894 static struct pci_driver netdrv_pci_driver = {
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,
1902 #endif /* CONFIG_PM */
1903 };我们可以看出来,并不是这个结构体的所有成员我们都要操作,我们只管其中最关键的几个就行了。
那上面的几个分别什么作用呢?
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函数。这里我将只说明驱动-设备匹配相关的内容,过程中看到的其他内容不在讨论范围内。我们将调用过程加粗和标红。
1103 int __pci_register_driver(struct pci_driver *drv, struct module *owner,
1104 const char *mod_name)
1105 {
1106 int error;
1107
1108 /* initialize common driver fields */
1109 drv->driver.name = drv->name;
1110 drv->driver.bus = &pci_bus_type;
1111 drv->driver.owner = owner;
1112 drv->driver.mod_name = mod_name;
1113
1114 spin_lock_init(&drv->dynids.lock);
1115 INIT_LIST_HEAD(&drv->dynids.list);
1116
1117 /* register with core */
1118 <strong><span style=&#34;color:#ff0000;&#34;>error = driver_register(&drv->driver);</span></strong>
1119 if (error)
1120 goto out;
1121
。。。。。。。。
1137 }__pci_register_driver函数中,调用driver_register,在总线上注册驱动。
222 int driver_register(struct device_driver *drv)
223 {
224 int ret;
225 struct device_driver *other;
226
227 BUG_ON(!drv->bus->p);
228
229 if ((drv->bus->probe && drv->probe) ||
230 (drv->bus->remove && drv->remove) ||
231 (drv->bus->shutdown && drv->shutdown))
232 printk(KERN_WARNING &#34;Driver &#39;%s&#39; needs updating - please use &#34;
233 &#34;bus_type methods\n&#34;, drv->name);
234
235 other = driver_find(drv->name, drv->bus);
236 if (other) {
237 put_driver(other);
238 printk(KERN_ERR &#34;Error: Driver &#39;%s&#39; is already registered, &#34;
239 &#34;aborting...\n&#34;, drv->name);
240 return -EBUSY;
241 }
242
243 <strong><span style=&#34;color:#ff0000;&#34;>ret = bus_add_driver(drv);</span></strong>
244 if (ret)
245 return ret;
246 ret = driver_add_groups(drv, drv->groups);
247 if (ret)
248 bus_remove_driver(drv);
249 return ret;
250 }driver_register中调用bus_add_driver,将设备驱动添加到总线上。
625 int bus_add_driver(struct device_driver *drv)
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 &#34;%s&#34;, drv->name);
648 if (error)
649 goto out_unregister;
650
651 if (drv->bus->p->drivers_autoprobe) {
652 <strong><span style=&#34;color:#ff0000;&#34;>error = driver_attach(drv);</span></strong>
653 if (error)
654 goto out_unregister;
655 }
。。。。。。。。。。。。。。。
690 }
303 int driver_attach(struct device_driver *drv)
304 {
305 return <strong><span style=&#34;color:#ff0000;&#34;>bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);</span></strong>
306 }可以看出来,上面讲驱动程序追加到总线上之后,现在开始将设备与驱动进行匹配了。
285 int bus_for_each_dev(struct bus_type *bus, struct device *start,
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));
297 while ((dev = next_device(&i)) && !error)
298 <span style=&#34;color:#ff0000;&#34;>error = fn(dev, data);</span>
299 klist_iter_exit(&i);
300 return error;
301 }这里的fn就是__driver_attach函数,我们来看一下它干了什么:
265 static int __driver_attach(struct device *dev, void *data)
266 {
267 struct device_driver *drv = data;
。。。。。。。。。。。。。。。
279 <strong>if (!driver_match_device(drv, dev))</strong>
280 return 0;
281
282 if (dev->parent) /* Needed for USB */
283 device_lock(dev->parent);
284 device_lock(dev);
285 if (!dev->driver)
286 <strong><span style=&#34;color:#ff0000;&#34;>driver_probe_device(drv, dev);</span></strong>
287 device_unlock(dev);
288 if (dev->parent)
289 device_unlock(dev->parent);
290
291 return 0;
292 }279行的driver_match_device函数就是用来为driver匹配device的
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中注册的match函数来进行匹配了,匹配的具体过程就不看了。再回到上面的__driver_attach函数的driver_probe_device中。
200 int driver_probe_device(struct device_driver *drv, struct device *dev)
201 {
202 int ret = 0;
203
204 if (!device_is_registered(dev))
205 return -ENODEV;
206
207 pr_debug(&#34;bus: &#39;%s&#39;: %s: matched device %s with driver %s\n&#34;,
208 drv->bus->name, __func__, dev_name(dev), drv->name);
209
210 pm_runtime_get_noresume(dev);
211 pm_runtime_barrier(dev);
212 ret = really_probe(dev, drv);
213 pm_runtime_put_sync(dev);
214
215 return ret;
216 }
108 static int really_probe(struct device *dev, struct device_driver *drv)
109 {
110 int ret = 0;
111
112 atomic_inc(&probe_count);
113 pr_debug(&#34;bus: &#39;%s&#39;: %s: probing driver %s with device %s\n&#34;,
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 &#34;%s: driver_sysfs_add(%s) failed\n&#34;,
120 __func__, dev_name(dev));
121 goto probe_failed;
122 }
123
124 if (dev->bus->probe) {
125 ret = dev->bus->probe(dev);
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. 总结
我们来总结一下设备驱动程序初始化的几个步骤:
- 根据设备类型,构造所需描述驱动的结构体。该结构体需要继承struct device_driver结构,并给几个重要的成员初始化。
- 通过module_init宏调用驱动程序的初始化函数xx_init_module,在初始化函数中注册驱动程序。
3.驱动程序会遍历总线上的struct device和struct device_driver两条链表,调用总线的match函数,对设备与驱动程序进行匹配。
4.如果设备与驱动程序匹配成功,则调用驱动程序的probe函数。probe函数的实现,需要根据驱动程序的功能来定,不属于本文的讨论范围。
原文作者:首页 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛
原文地址:linux设备驱动程序注册过程详解 - 圈点 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛(版权归原文作者所有,侵权联系删除)
|
|