📄 linux设备驱动程序学习(14)-linux设备模型(各环节的整合) - linux设备驱动程序 - tekkaman ninja.htm
字号:
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR><SPAN
style="COLOR: #0000cc">}</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
<P> 在 device_register 函数中, 驱动核心初始化
device 结构体中的许多成员, 向 kobject 核心注册设备的 kobject (
导致热插拔事件产生), 接着添加设备到其 parent
节点所拥有的设备链表中。此后所有的设备都可通过正确的顺序被访问,
并知道其位于设备层次中的哪一点。</P>
<P>
设备接着被添加到总线相关的设备链表(包含了所有向总线注册的设备)中。接着驱动核心遍历这个链表,
为每个驱动程序调用该总线的match函数。</P>
<P> <FONT color=#0000ff>
match函数</FONT>主要是将驱动核心传递给它的 struct device 和 struct
device_driver转换为特定的设备、驱动结构体 ,检查设备的特定信息,
以确定驱动程序是否支持该设备:</P>
<P>若不支持, 函数返回 0 给驱动核心,这样驱动核心移向链表中的下一个驱动;</P>
<P>若支持, 函数返回 1 给驱动核心,使驱动核心设置struct device 中的
driver 指针指向这个驱动, 并调用在 struct device_driver 中指定的
probe 函数.</P>
<P> <FONT color=#0000ff>probe
函数</FONT>(又一次) 将驱动核心传递给它的 struct device 和 struct
device_driver转换为特定的设备、驱动结构体 ,并再次验证这个驱动是否支持这个设备,
递增设备的引用计数, 接着调用总线驱动的 probe 函数:</P>
<P>若总线 probe
函数认为它不能处理这个设备,则返回一个负的错误值给驱动核心,这样驱动核心移向链表中的下一个设备;</P>
<P>若这个 probe 函数能够处理这个设备, 则初始化这个设备, 并返回 0
给驱动核心。这会使驱动核心添加设备到与这个特定驱动所绑定的设备链表中, 并在
/sys/bus的总线目录中的 drivers
目录中创建一个到这个设备符号链接(指向/sys/devices中的设备),使用户准确知道哪个驱动被绑定到了哪个设备。</P>
<DIV></DIV>
<DIV><STRONG><FONT
color=#0000ff>(2)设备的注销</FONT></STRONG></DIV>
<DIV> 在驱动程序中对设备进行注销的核心函数是:</DIV>
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><SPAN
style="COLOR: #0000ff">void</SPAN>
device_unregister<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">struct</SPAN> device
<SPAN style="COLOR: #0000cc">*</SPAN> dev<SPAN
style="COLOR: #0000cc">)</SPAN></SPAN></CODE></P></TD></TR></TBODY></TABLE>在
device_unregister 函数中,
驱动核心将删除这个设备的驱动程序(如果有)指向这个设备的符号链接,
并从它的内部设备链表中删除该设备, 再以 device 结构中的 struct kobject
指针为参数,调用 kobject_del。kobject_del 函数引起用户空间的 hotplug
调用,表明 kobject 现在从系统中删除, 接着删除所有该 kobject
以前创建的、与之相关联的 sysfs 文件和目录。kobject_del 函数也去除设备自身的
kobject 引用。此后, 所有的和这个设备关联的 sysfs 入口被去除,
并且和这个设备关联的内存被释放。
<P><STRONG><FONT
color=#0000ff>(3)驱动程序的注册</FONT></STRONG></P>
<P> 在驱动程序中对驱动程序进行注册的核心函数是:
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000ff">int</SPAN>
driver_register<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">struct</SPAN>
device_driver <SPAN
style="COLOR: #0000cc">*</SPAN> drv<SPAN
style="COLOR: #0000cc">)</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
<P>driver_register 函数初始化 struct device_driver
结构体(包括 一个设备链表及其增删对象函数 和 一个自旋锁), 然后调用
bus_add_driver 函数。</P>
<P>bus_add_driver进行如下操作:</P>
<P>(1)查找驱动关联的总线:若未找到,
立刻返回负的错误值;<BR>(2)根据驱动的名字和关联的总线,创建驱动的 sysfs
目录;<BR>(3)获取总线的内部锁,
遍历所有的已经注册到总线的设备,为这些设备调用match函数,
若成功,进行剩下的绑定过程。(类似注册设备,不再赘述)</P>
<P><STRONG><FONT
color=#0000ff>(4)驱动程序的注销</FONT></STRONG></P><FONT
color=#000000 size=2>
删除驱动程序是一个简单的过程,在驱动程序中对驱动程序进行注销的核心函数是:
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000ff">void</SPAN>
driver_unregister<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">struct</SPAN>
device_driver <SPAN
style="COLOR: #0000cc">*</SPAN> drv<SPAN
style="COLOR: #0000cc">)</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></FONT>deiver_unregister
函数通过清理在 sysfs 树中连接到这个驱动入口的 sysfs
属性,来完成一些基本的管理工作。然后遍历所有属于该驱动的设备,为其调用 release
函数(类似设备从系统中删除时调用 release 函数)。
<P>
<TABLE
style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid"
align=center>
<TBODY>
<TR>
<TD>
<P>在所有的设备与驱动程序脱离后,通常在驱动程序中会使用下面两个函数:</P>
<P>down(&drv->unload_sem);<BR>up(&drv->unload_sem);</P>
<P>它们在函数返回给调用者之前完成。这样做是因为在安全返回前,代码需要等待所有的对这个驱动的引用计数为
0。<BR>模块卸载时,通常都要调用 driver_unregister 函数作为退出的方法。
只要驱动程序被设备引用并且等待这个锁时,模块就需要保留在内存中。这使得内核知道何时可以安全从内存删除驱动。</P></TD></TR></TBODY></TABLE></P>
<P>
<HR id=null>
<P></P>
<P><STRONG><FONT color=#0000ff
size=3>四、ARM9开发板实验</FONT></STRONG></P>
<DIV><FONT color=#0000ff
size=3><STRONG>实验源码:</STRONG></FONT><A
href="http://blogimg.chinaunix.net/blog/upfile2/080109150139.rar">http://blogimg.chinaunix.net/blog/upfile2/080109150139.rar</A></DIV>
<DIV> </DIV><STRONG><FONT color=#0000ff
size=3>实验过程:</FONT></STRONG>
<DIV>
<TABLE style="BORDER-COLLAPSE: collapse"
borderColor=#999999 cellSpacing=0 cellPadding=0
width="95%" bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000cc">[</SPAN>Tekkaman2440@SBC2440V4<SPAN
style="COLOR: #0000cc">]</SPAN><SPAN
style="COLOR: #0000cc">#</SPAN>insmod <SPAN
style="COLOR: #0000cc">/</SPAN>lib<SPAN
style="COLOR: #0000cc">/</SPAN>modules<SPAN
style="COLOR: #0000cc">/</SPAN>lddbus<SPAN
style="COLOR: #0000cc">.</SPAN>ko<BR>Mount
lddbus ok <SPAN
style="COLOR: #0000cc">!</SPAN><BR>Bus device is
ldd0 <SPAN
style="COLOR: #0000cc">!</SPAN><BR>You can see
me in sys<SPAN
style="COLOR: #0000cc">/</SPAN>module<SPAN
style="COLOR: #0000cc">/</SPAN> <SPAN
style="COLOR: #0000cc">,</SPAN> sys<SPAN
style="COLOR: #0000cc">/</SPAN>devices<SPAN
style="COLOR: #0000cc">/</SPAN> <SPAN
style="COLOR: #0000ff">and</SPAN> sys<SPAN
style="COLOR: #0000cc">/</SPAN>bus<SPAN
style="COLOR: #0000cc">/</SPAN> <SPAN
style="COLOR: #0000cc">!</SPAN><BR><SPAN
style="COLOR: #0000cc">[</SPAN>Tekkaman2440@SBC2440V4<SPAN
style="COLOR: #0000cc">]</SPAN><SPAN
style="COLOR: #0000cc">#</SPAN>tree <SPAN
style="COLOR: #0000cc">-</SPAN>AC <SPAN
style="COLOR: #0000cc">/</SPAN>sys<SPAN
style="COLOR: #0000cc">/</SPAN>module<SPAN
style="COLOR: #0000cc">/</SPAN>lddbus<SPAN
style="COLOR: #0000cc">/</SPAN> <SPAN
style="COLOR: #0000cc">/</SPAN>sys<SPAN
style="COLOR: #0000cc">/</SPAN>devices<SPAN
style="COLOR: #0000cc">/</SPAN>ldd0<SPAN
style="COLOR: #0000cc">/</SPAN> <SPAN
style="COLOR: #0000cc">/</SPAN>sys<SPAN
style="COLOR: #0000cc">/</SPAN>bus<SPAN
style="COLOR: #0000cc">/</SPAN>ldd<SPAN
style="COLOR: #0000cc">/</SPAN><BR><SPAN
style="COLOR: #0000cc">/</SPAN>sys<SPAN
style="COLOR: #0000cc">/</SPAN>module<SPAN
style="COLOR: #0000cc">/</SPAN>lddbus<SPAN
style="COLOR: #0000cc">/</SPAN><BR>├──
holders<BR>├── <SPAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -