📄 linux设备驱动程序学习(12)-linux设备模型(底层原理简介) - linux设备驱动程序 - tekkaman ninja.htm
字号:
的引用计数并返回一个指向 kobject 的指针,否则返回
NULL。必须始终测试返回值以免产生竞态*/</SPAN><BR><SPAN
style="COLOR: #0000ff">void</SPAN>
kobject_put<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">struct</SPAN> kobject
<SPAN style="COLOR: #0000cc">*</SPAN>kobj<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><SPAN
style="COLOR: #ff9900">/*递减引用计数并在可能的情况下释放这个对象*/</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></FONT></P>
<P><FONT face=新宋体>注意:kobject _init 设置这个引用计数为
1,因此创建一个 kobject时, 当这个初始化引用不再需要,应当确保采取 kobject_put
调用。同理:struct cdev 的引用计数实现如下:</FONT>
<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">struct</SPAN> kobject
<SPAN
style="COLOR: #0000cc">*</SPAN>cdev_get<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">struct</SPAN> cdev <SPAN
style="COLOR: #0000cc">*</SPAN>p<SPAN
style="COLOR: #0000cc">)</SPAN> <BR><SPAN
style="COLOR: #0000cc">{</SPAN><BR> <SPAN
style="COLOR: #0000ff">struct</SPAN> module
<SPAN style="COLOR: #0000cc">*</SPAN>owner <SPAN
style="COLOR: #0000cc">=</SPAN> p<SPAN
style="COLOR: #0000cc">-</SPAN><SPAN
style="COLOR: #0000cc">></SPAN>owner<SPAN
style="COLOR: #0000cc">;</SPAN><BR> <SPAN
style="COLOR: #0000ff">struct</SPAN> kobject
<SPAN style="COLOR: #0000cc">*</SPAN>kobj<SPAN
style="COLOR: #0000cc">;</SPAN><BR> <SPAN
style="COLOR: #0000ff">if</SPAN> <SPAN
style="COLOR: #0000cc">(</SPAN>owner <SPAN
style="COLOR: #0000cc">&</SPAN><SPAN
style="COLOR: #0000cc">&</SPAN> <SPAN
style="COLOR: #0000cc">!</SPAN>try_module_get<SPAN
style="COLOR: #0000cc">(</SPAN>owner<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">)</SPAN><BR> <SPAN
style="COLOR: #0000ff">return</SPAN> <SPAN
style="COLOR: #ff0000">NULL</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR> kobj
<SPAN style="COLOR: #0000cc">=</SPAN>
kobject_get<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">&</SPAN>p<SPAN
style="COLOR: #0000cc">-</SPAN><SPAN
style="COLOR: #0000cc">></SPAN>kobj<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR> <SPAN
style="COLOR: #0000ff">if</SPAN> <SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000cc">!</SPAN>kobj<SPAN
style="COLOR: #0000cc">)</SPAN><BR> module_put<SPAN
style="COLOR: #0000cc">(</SPAN>owner<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN><BR> <SPAN
style="COLOR: #0000ff">return</SPAN> kobj<SPAN
style="COLOR: #0000cc">;</SPAN><BR><SPAN
style="COLOR: #0000cc">}</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE><BR></P>
<P><FONT face=新宋体>创建一个对 cdev
结构的引用时,还需要创建包含它的模块的引用。因此, cdev_get 使用
try_module_get 来试图递增这个模块的使引用计数。如果这个操作成功,
kobject_get 被同样用来递增 kobject 的引用计数。kobject_get
可能失败, 因此这个代码检查 kobject_get
的返回值,如果调用失败,则释放它的对模块的引用计数。</FONT></P>
<P><FONT color=#0000ff><STRONG>release 函数和 kobject
类型</STRONG></FONT></P>
<P><FONT face=新宋体>引用计数不由创建 kobject 的代码直接控制,当
kobject
的最后引用计数消失时,必须异步通知,而后kobject中ktype所指向的kobj_type结构体包含的release函数会被调用。通常原型如下:</FONT>
<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>
my_object_release<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">struct</SPAN> kobject
<SPAN style="COLOR: #0000cc">*</SPAN>kobj<SPAN
style="COLOR: #0000cc">)</SPAN><BR><SPAN
style="COLOR: #0000cc">{</SPAN><BR> <SPAN
style="COLOR: #0000ff">struct</SPAN> my_object
<SPAN style="COLOR: #0000cc">*</SPAN>mine <SPAN
style="COLOR: #0000cc">=</SPAN>
container_of<SPAN
style="COLOR: #0000cc">(</SPAN>kobj<SPAN
style="COLOR: #0000cc">,</SPAN> <SPAN
style="COLOR: #0000ff">struct</SPAN>
my_object<SPAN style="COLOR: #0000cc">,</SPAN>
kobj<SPAN style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN> <BR><SPAN
style="COLOR: #ff9900">/* Perform any additional
cleanup on this object, then...
*/</SPAN><BR> kfree<SPAN
style="COLOR: #0000cc">(</SPAN>mine<SPAN
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><FONT face=新宋体>每个 kobject 必须有一个release函数, 并且这个
kobject 必须在release函数被调用前保持不变( 稳定状态 ) 。这样,每一个
kobject 需要有一个关联的 kobj_type 结构,指向这个结构的指针能在 2
个不同的地方找到:</FONT></P>
<P><FONT face=新宋体>(1)kobject
结构自身包含一个成员(ktype)指向kobj_type ;</FONT></P>
<P><FONT face=新宋体>(2)如果这个 kobject 是一个 kset 的成员,
kset 会提供kobj_type 指针。</FONT>
<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">struct</SPAN> kset <SPAN
style="COLOR: #0000cc">{</SPAN><BR><FONT
color=#ff0000> <SPAN
style="COLOR: #0000ff">struct</SPAN>
kobj_type <SPAN
style="COLOR: #0000cc">*</SPAN> ktype<SPAN
style="COLOR: #0000cc">; <FONT
color=#ff9900>/*指向该kset对象类型的指针*/</FONT></SPAN></FONT><BR> <SPAN
style="COLOR: #0000ff">struct</SPAN>
list_head <FONT
color=#000000> <SPAN
style="COLOR: #ff0000">list</SPAN></FONT><SPAN
style="COLOR: #0000cc">;<FONT
color=#ff9900>/*用于连接该kset中所有kobject以形成环形链表的链表头*/</FONT></SPAN><BR> spinlock_t list_lock<SPAN
style="COLOR: #0000cc">;<FONT
color=#ff9900>/*用于避免竞态的自旋锁*/</FONT></SPAN><BR> <SPAN
style="COLOR: #0000ff">struct</SPAN>
kobject kobj<SPAN
style="COLOR: #0000cc">; <FONT
color=#ff9900>/*嵌入的kobject*/</FONT></SPAN><BR> <SPAN
style="COLOR: #0000ff">struct</SPAN> <FONT
color=#ff0000>kset_uevent_ops <SPAN
style="COLOR: #0000cc">*</SPAN>
uevent_ops</FONT><SPAN style="COLOR: #0000cc">;
</SPAN></FONT></SPAN></CODE></P>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: #000000"><FONT face=新宋体><SPAN
style="COLOR: #0000cc"><FONT
color=#ff9900>/*<FONT color=#ff0000>原有的struct
kset_hotplug_ops *
hotplug_ops;已经不存在,被kset_uevent_ops 结构体替换,在热插拔操作中会介绍</FONT>*/</FONT></SPAN><BR><SPAN
style="COLOR: #0000cc">}</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
<P><FONT face=新宋体>以下宏用以查找指定kobject的kobj_type 指针:
<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">struct</SPAN> kobj_type
<SPAN
style="COLOR: #0000cc">*</SPAN>get_ktype<SPAN
style="COLOR: #0000cc">(</SPAN><SPAN
style="COLOR: #0000ff">struct</SPAN> kobject
<SPAN style="COLOR: #0000cc">*</SPAN>kobj<SPAN
style="COLOR: #0000cc">)</SPAN><SPAN
style="COLOR: #0000cc">;</SPAN></FONT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -