📄 linux设备驱动程序学习(3)-并发和竞态 - linux设备驱动程序 - tekkaman ninja.htm
字号:
style="COLOR: rgb(0,0,204)">;</SPAN><BR> scull_devices<SPAN
style="COLOR: rgb(0,0,204)">[</SPAN>i<SPAN
style="COLOR: rgb(0,0,204)">]</SPAN><SPAN
style="COLOR: rgb(0,0,204)">.</SPAN>qset <SPAN
style="COLOR: rgb(0,0,204)">=</SPAN>
scull_qset<SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR> init_MUTEX<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,204)">&</SPAN>scull_devices<SPAN
style="COLOR: rgb(0,0,204)">[</SPAN>i<SPAN
style="COLOR: rgb(0,0,204)">]</SPAN><SPAN
style="COLOR: rgb(0,0,204)">.</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;<SPAN
style="COLOR: rgb(0,0,0)"><SPAN
style="COLOR: rgb(255,153,0)"><FONT
color=#ff0000>/* 注意顺序:先初始化好互斥信号量
,再使scull_devices可用。*/</FONT></SPAN></SPAN></SPAN><BR> scull_setup_cdev<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,204)">&</SPAN>scull_devices<SPAN
style="COLOR: rgb(0,0,204)">[</SPAN>i<SPAN
style="COLOR: rgb(0,0,204)">]</SPAN><SPAN
style="COLOR: rgb(0,0,204)">,</SPAN> i<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR> <SPAN
style="COLOR: rgb(0,0,204)">}</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></DIV>
<DIV> </DIV>
<DIV><FONT color=#ff0000
size=3>而且要确保在不拥有信号量的时候不会访问scull_dev结构体。</FONT></DIV>
<DIV> </DIV>
<DIV> <FONT color=#0000ff
size=4><STRONG>读取者/写入者信号量</STRONG></FONT></DIV>
<DIV>只读任务可并行完成它们的工作,而不需要等待其他读取者退出临界区。Linux内核提供了读取者/写入者信号量“rwsem”,使用是必须包括<FONT
color=#0000ff><linux/rwsem.h></FONT> 。</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: rgb(0,0,0)"><FONT face=新宋体><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
init_rwsem<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></DIV>
<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: rgb(0,0,0)"><FONT face=新宋体><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
down_read<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">int</SPAN>
down_read_trylock<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
up_read<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></DIV>
<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: rgb(0,0,0)"><FONT face=新宋体><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
down_write<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">int</SPAN>
down_write_trylock<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
up_write<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN></FONT></SPAN></CODE></P>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: rgb(0,0,0)"><FONT face=新宋体><SPAN
style="COLOR: rgb(0,0,204)"></SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
downgrade_write<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
rw_semaphore <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>sem<FONT
color=#ff9933><SPAN
style="COLOR: rgb(0,0,204)">)</SPAN></FONT><FONT
color=#000000><SPAN
style="COLOR: rgb(0,0,204)">;<FONT
color=#ff9900>/*该函数用于把<FONT
color=#ff0000>写者降级为读者</FONT>,这有时是必要的。因为写者是排他性的,因此在写者保持读写信号量期间,任何读者或写者都将无法访问该读写信号量保护的共享资源,对于那些当前条件下不需要写访问的写者,降级为读者将,使得等待访问的读者能够立刻访问,从而增加了并发性,提高了效率。*/</FONT></SPAN></FONT></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></DIV>
<DIV> </DIV>
<DIV>
<P>一个 rwsem 允许一个写者或无限多个读者来拥有该信号量. 写者有优先权;
当某个写者试图进入临界区, 就不会允许读者进入直到写者完成了它的工作.
如果有大量的写者竞争该信号量,则这个实现可能导致读者“饿死”,即可能会长期拒绝读者访问。因此,
rwsem 最好用在很少请求写的时候, 并且写者只占用短时间.</P></DIV>
<DIV><FONT style="FONT-WEIGHT: bold" size=4><SPAN
style="COLOR: rgb(0,1,255)">completion</SPAN></FONT><BR>completion是一种轻量级的机制,它允许一个线程告诉另一个线程某个工作已经完成。代码必须包含<linux/completion.h>。使用的代码如下:
<BR>
<DIV> </DIV>
<TABLE
style="WIDTH: 556px; BORDER-COLLAPSE: collapse; HEIGHT: 372px"
borderColor=#999999 cellSpacing=0 cellPadding=0
bgColor=#f1f1f1 border=1>
<TBODY>
<TR>
<TD>
<P
style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN
style="COLOR: rgb(0,0,0)">DECLARE_COMPLETION<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN>my_completion<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><SPAN
style="COLOR: rgb(255,153,0)">/*
创建completion(声明+初始化) */</SPAN><BR><BR><SPAN
style="COLOR: rgb(255,153,0)">/////////////////////////////////////////////////////////<BR></SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
completion my_completion<SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><SPAN
style="COLOR: rgb(255,153,0)">/* 动态声明completion
结构体*/</SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">static</SPAN> <SPAN
style="COLOR: rgb(0,0,255)">inline</SPAN> <SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
init_completion<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,204)">&</SPAN>my_completion<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><SPAN
style="COLOR: rgb(255,153,0)">/*动态初始化completion*/</SPAN><BR><BR><SPAN
style="COLOR: rgb(255,153,0)">///////////////////////////////////////////////////////<BR></SPAN><BR><SPAN
style="COLOR: rgb(0,0,255)">void</SPAN>
wait_for_completion<SPAN
style="COLOR: rgb(0,0,204)">(</SPAN><SPAN
style="COLOR: rgb(0,0,255)">struct</SPAN>
completion <SPAN
style="COLOR: rgb(0,0,204)">*</SPAN>c<SPAN
style="COLOR: rgb(0,0,204)">)</SPAN><SPAN
style="COLOR: rgb(0,0,204)">;</SPAN><SPAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -