⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch14s06.html

📁 Linux设备驱动经典
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html xmlns:cf="http://docbook.sourceforge.net/xmlns/chunkfast/1.0"><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>14.6.&#160;集成起来-Linux设备驱动第三版(中文版)</title><meta name="description" content="驱动开发" /><meta name="keywords" content="Linux设备驱动,中文版,第三版,ldd,linux device driver,驱动开发,电子版,程序设计,软件开发,开发频道" /><meta name="verify-v1" content="5asbXwkS/Vv5OdJbK3Ix0X8osxBUX9hutPyUxoubhes=" /><link rel="stylesheet" href="docbook.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.69.0"><link rel="start" href="index.html" title="Linux 设备驱动 Edition 3"><link rel="up" href="ch14.html" title="第&#160;14&#160;章&#160;Linux 设备模型"><link rel="prev" href="ch14s05.html" title="14.5.&#160;类"><link rel="next" href="ch14s07.html" title="14.7.&#160;热插拔"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">14.6.&#160;集成起来</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch14s05.html">上一页</a>&#160;</td><th width="60%" align="center">第&#160;14&#160;章&#160;Linux 设备模型</th><td width="20%" align="right">&#160;<a accesskey="n" href="ch14s07.html">下一页</a></td></tr></table><hr></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="PuttingItAllTogether.sect1"></a>14.6.&#160;集成起来</h2></div></div></div><p>为更好理解驱动模型做什么, 让我们通览一个设备在内核中的生命周期的阶段. 我们描述 PCI 子系统如何与驱动模型交互, 一个驱动如何被加入和去除的基本概念, 以及一个设备如何从系统中被加入和去除. 这些细节, 即便特别地描述 PCI 内核代码, 适用所有其他的使用驱动核心来管理它们的驱动和设备的子系统.</p><p>PCI 核心, 驱动核心和单独的 PCI 驱动之间的交互是非常复杂, 如同图 <a href="ch14s06.html#ldd3-14-3.fig" title="图&#160;14.3.&#160;创建设备过程">创建设备过程</a>所示.</p><div class="figure"><a name="ldd3-14-3.fig"></a><p class="title"><b>图&#160;14.3.&#160;创建设备过程</b></p><div><img src="images/snagitldd3/ldd3-14-3.png" alt="创建设备过程"></div></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="AddaDevice.sect2"></a>14.6.1.&#160;添加一个设备</h3></div></div></div><p>PCI 子系统声明一个单个 struct bus_type 称为 pci_bus_type, 它使用下列值初始化:</p><pre class="programlisting">struct bus_type pci_bus_type = { .name  = "pci",  .match  = pci_bus_match,  .hotplug  = pci_hotplug,  .suspend  = pci_device_suspend,  .resume  = pci_device_resume,  .dev_attrs = pci_dev_attrs, };</pre><p>这个 pci_bus_type 变量被注册到驱动内核, 当 PCI 子系统通过对 bus_register 的调用被加载入内核时. 当这个发生时, 驱动核心创建一个 sysfs 目录在 /sys/bus/pci 里, 它包含 2 个目录: devices 和 drivers.</p><p>所有的 PCI 驱动必须定义一个 struct pci_driver 变量, 它定义了这个 PCI 驱动能够做的不同的功能(更多的关于 PCI 子系统和如何编写一个 PCI 驱动的信息, 见 12 章). 那个结构包含一个 struct device_driver, 它接着被 PCI 核心初始化, 当 PCI 驱动被注册时.</p><pre class="programlisting">/* initialize common driver fields */drv-&gt;driver.name = drv-&gt;name;drv-&gt;driver.bus = &amp;pci_bus_type;drv-&gt;driver.probe = pci_device_probe;drv-&gt;driver.remove = pci_device_remove; drv-&gt;driver.kobj.ktype = &amp;pci_driver_kobj_type;</pre><p>这个代码为驱动建立总线来指向 pci_bus_type 以及使 probe 和 remove 函数来指向 PCI 核心内的函数. 驱动的 kobject 的 ktype 被设置为变量 pci_driver_kobj_type, 为使 PCI 驱动的属性文件正常工作. 接着 PCI 核心注册 PCI 驱动到驱动核心:</p><pre class="programlisting">/* register with core */error = driver_register(&amp;drv-&gt;driver);</pre><p>驱动现在准备好被绑定到任何一个它支持的 PCI 设备.</p><p>PCI 核心, 在来自特定结构的实际和 PCI 总线交谈的代码的帮助下, 开始探测 PCI 地址空间, 查找所有的 PCI 设备. 当一个PCI 设备被发现, PCI 核心在内存中创建一个 struct pci_dev 类型的新变量. struct pci_dev 结构的一部分看来如下:</p><pre class="programlisting">struct pci_dev { /* ... */ unsigned int devfn; unsigned short vendor; unsigned short device; unsigned short subsystem_vendor; unsigned short subsystem_device; unsigned int class; /* ... */ struct pci_driver *driver; /* ... */ struct device dev; /* ... */}; </pre><p>这个 PCI 设备的总线特定的成员被 PCI 核心初始化( devfn, vendor, device, 和其他成员), 并且 struct device 变量的 parent 变量被设置为这个 PCI 设备所在的 PCI 总线设备. bus 变量被设置指向 pci_bus_type 结构. 接下来 name 和 bus_id 变量被设置, 根据读自 PCI 设备的 name 和 ID.</p><p>在 PCI 设备结构被初始化之后, 设备被注册到驱动核心, 使用:</p><pre class="programlisting">device_register(&amp;dev-&gt;dev); </pre><p>在 device_register 函数中, 驱动核心初始化设备的许多成员, 注册设备的 kobject 到 kobject 核心( 它导致一个热插拔事件产生, 但是我们在本章后面讨论), 接着添加设备到驱动的 parent 所持有的设备列表中. 完成这个使所有的设备可被以正确的顺序浏览, 一直知道每一个位于设备层次中哪里.</p><p>设备接着被添加到所有设备的总线特定的列表中, 在本例中, pci_bus_type 列表. 接着注册到这个总线的所有驱动的列表被检查, 并且总线的匹配功能被调用给每个驱动, 指定这个设备. 对于 pci_bus_type 总线, 匹配函数被 PCI 核心设定为指向 pci_bus_match 函数, 在设备被提交给驱动核心前.</p><p>pci_bus_match 函数转换驱动核心传递给它的 struct device 为一个 struct pci_dev. 它还转换 struct device_driver 为一个 struct pci_driver , 并接着查看设备的 PCI 设备特定信息和驱动, 看是否这个驱动声明它能够支持这类设备. 如果匹配不成功, 函数返回 0 给驱动核心, 并且驱动核心移向列表中的下一个驱动.</p><p>如果匹配成功, 函数返回 1 给驱动核心. 这使驱动核心设置struct device 中的驱动指针指向这个驱动, 并且接着调用在 struct device_driver 中特定的 probe 函数.</p>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -