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

📄 ch14s06.html

📁 介绍Linux设备驱动开发
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<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="author" content="华星在线 www.21cstar.com QQ:610061171" /> 
<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/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 + -