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

📄 linux设备驱动程序学习(11)-中断处理 - linux设备驱动程序 - tekkaman ninja.htm

📁 Linux设备驱动程序学习(11)-中断处理 - Linux设备驱动程序.rar
💻 HTM
📖 第 1 页 / 共 5 页
字号:
                        <TABLE 
                        style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word" 
                        cellSpacing=0 cellPadding=0 width="100%" border=0>
                          <TBODY>
                          <TR>
                            <TD width="100%">
                              <DIV id=art style="MARGIN: 15px" width="100%">
                              <P align=center><FONT color=#0000ff 
                              size=4><STRONG>Linux设备驱动程序学习(11)-中断处理</STRONG></FONT> 
                              </P>
                              <P>可以让设备在产生某个事件时通知处理器的方法就是中断。一个“中断”仅是一个信号,当硬件需要获得处理器对它的关注时,就可以发送这个信号。<FONT 
                              color=#ff0000> Linux 
                              处理中断的方式非常类似在用户空间处理信号的方式。</FONT> 
                              大多数情况下,一个驱动只需要为它的设备的中断注册一个处理例程,并当中断到来时进行正确的处理。本质上来讲,中断处理例程和其他的代码并行运行。因此,它们不可避免地引起并发问题,并竞争数据结构和硬件。 
                              透彻地理解并发控制技术对中断来讲非常重要。 
                              <HR id=null>

                              <P></P>
                              <P><FONT color=#0000ff 
                              size=4><STRONG>安装中断处理例程</STRONG></FONT></P>
                              <P>内核维护了一个中断信号线的注册表,类似于 I/O 
                              端口的注册表。模块在使用中断前要先请求一个中断通道(或者 
                              IRQ中断请求),并在使用后释放它。所用的函数声明在 <FONT 
                              color=#0000ff>&lt;linux/interrupt.h&gt;</FONT> 
                              (在此文件中并未真正包含,是通过它include的文件间接包含的,函数在/kernel/irq/Manage.h中),中断注册和释放的函数接口如下: 

                              <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> 
                                request_irq<SPAN 
                                style="COLOR: #0000cc">(</SPAN><SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">int</SPAN> irq<SPAN 
                                style="COLOR: #0000cc">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;irqreturn_t 
                                <SPAN style="COLOR: #0000cc">(</SPAN><SPAN 
                                style="COLOR: #0000cc">*</SPAN>handler<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">(</SPAN><SPAN 
                                style="COLOR: #0000ff">int</SPAN><SPAN 
                                style="COLOR: #0000cc">,</SPAN> <SPAN 
                                style="COLOR: #0000ff">void</SPAN> <SPAN 
                                style="COLOR: #0000cc">*</SPAN><SPAN 
                                style="COLOR: #0000cc">,</SPAN> <SPAN 
                                style="COLOR: #0000ff">struct</SPAN> pt_regs 
                                <SPAN style="COLOR: #0000cc">*</SPAN><SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">long</SPAN> flags<SPAN 
                                style="COLOR: #0000cc">,</SPAN></FONT></SPAN></CODE></P>
                                <P 
                                style="MARGIN: 5px; LINE-HEIGHT: 150%"><CODE><SPAN 
                                style="COLOR: #000000"><SPAN 
                                style="COLOR: #0000cc"></SPAN><FONT 
                                face=新宋体>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">const</SPAN> <SPAN 
                                style="COLOR: #0000ff">char</SPAN> <SPAN 
                                style="COLOR: #0000cc">*</SPAN>dev_name<SPAN 
                                style="COLOR: #0000cc">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">void</SPAN> <SPAN 
                                style="COLOR: #0000cc">*</SPAN>dev_id<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR><BR><SPAN 
                                style="COLOR: #0000ff">void</SPAN> free_irq<SPAN 
                                style="COLOR: #0000cc">(</SPAN><SPAN 
                                style="COLOR: #0000ff">unsigned</SPAN> <SPAN 
                                style="COLOR: #0000ff">int</SPAN> irq<SPAN 
                                style="COLOR: #0000cc">,</SPAN> <SPAN 
                                style="COLOR: #0000ff">void</SPAN> <SPAN 
                                style="COLOR: #0000cc">*</SPAN>dev_id<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P><PRE class=programlisting><FONT color=#0000ff>request_irq</FONT> 的返回值: 0 指示成功,或返回一个负的错误码,如 -EBUSY 表示另一个驱动已经占用了你所请求的中断线。</PRE>
                              <P>函数的参数如下:</P>
                              <DIV class=variablelist>
                              <DL>
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>unsigned int irq</FONT> 
                                :</SPAN></SPAN>请求的中断号 
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>irqreturn_t 
                                (*handler)</FONT></SPAN></SPAN> :安装的处理函数指针。 
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>unsigned long flags</FONT> 
                                </SPAN></SPAN>:一个与中断管理相关的位掩码选项。 
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>const char *dev_name</FONT> 
                                :</SPAN></SPAN>传递给 request_irq 的字符串,用来在 
                                /proc/interrupts 来显示中断的拥有者。 
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>void *dev_id</FONT> 
                                </SPAN></SPAN>:用于共享中断信号线的指针。它是唯一的标识,在中断线空闲时可以使用它,驱动程序也可以用它来指向自己的私有数据区(来标识哪个设备产生中断)。若中断没有被共享,dev_id 
                                可以设置为 NULL,但推荐用它指向设备的数据结构。 
                                <DT>
                                <DT><FONT color=#0000ff><STRONG>flags 
                                中可以设置的位如下:</STRONG></FONT></DT></DL></DIV>
                              <DIV class=variablelist>
                              <DL>
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>SA_INTERRUPT</FONT> 
                                :</SPAN></SPAN>快速中断标志。快速中断处理例程运行在当前处理器禁止中断的状态下。 
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>SA_SHIRQ</FONT> </SPAN></SPAN>: 
                                在设备间共享中断标志。 
                                <DT><SPAN class=term><SPAN><FONT 
                                color=#0000ff>SA_SAMPLE_RANDOM</FONT> 
                                :该</SPAN></SPAN>位表示产生的中断能对 /dev/random 和 
                                /dev/urandom 使用的熵池(entropy pool)有贡献。 
                                读取这些设备会返回真正的随机数,从而有助于应用程序软件选择用于加密的安全密钥。 
                                若设备以真正随机的周期产生中断,就应当设置这个标志。若设备中断是可预测的,这个标志不值得设置。可能被攻击者影响的设备不应当设置这个标志。更多信息看 
                                drivers/char/random.c 的注释。</DT></DL></DIV>
                              <P>中断处理例程可在驱动初始化时或在设备第一次打开时安装。推荐在设备第一次打开、硬件被告知产生中断前时申请中断,因为可以共享有限的中断资源。这样调用 
                              free_irq 
                              的位置是设备最后一次被关闭、硬件被告知不用再中断处理器之后。但这种方式的缺点是必须为每个设备维护一个打开计数。</P>
                              <P>&nbsp;以下是中断申请的示例(并口): 
                              <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">if</SPAN> <SPAN 
                                style="COLOR: #0000cc">(</SPAN>short_irq <SPAN 
                                style="COLOR: #0000cc">&gt;</SPAN><SPAN 
                                style="COLOR: #0000cc">=</SPAN> 0<SPAN 
                                style="COLOR: #0000cc">)</SPAN><BR><SPAN 
                                style="COLOR: #0000cc">{</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result 
                                <SPAN style="COLOR: #0000cc">=</SPAN> 
                                request_irq<SPAN 
                                style="COLOR: #0000cc">(</SPAN>short_irq<SPAN 
                                style="COLOR: #0000cc">,</SPAN> 
                                short_interrupt<SPAN 
                                style="COLOR: #0000cc">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SA_INTERRUPT<SPAN 
                                style="COLOR: #0000cc">,</SPAN> <SPAN 
                                style="COLOR: #ff00ff">"short"</SPAN><SPAN 
                                style="COLOR: #0000cc">,</SPAN> <SPAN 
                                style="COLOR: #ff0000">NULL</SPAN><SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000ff">if</SPAN> <SPAN 
                                style="COLOR: #0000cc">(</SPAN>result<SPAN 
                                style="COLOR: #0000cc">)</SPAN> <SPAN 
                                style="COLOR: #0000cc">{</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk<SPAN 
                                style="COLOR: #0000cc">(</SPAN>KERN_INFO <SPAN 
                                style="COLOR: #ff00ff">"short: can't get 
                                assigned irq %i\n"</SPAN><SPAN 
                                style="COLOR: #0000cc">,</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;short_irq<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;short_irq 
                                <SPAN style="COLOR: #0000cc">=</SPAN> <SPAN 
                                style="COLOR: #0000cc">-</SPAN>1<SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000cc">}</SPAN> <SPAN 
                                style="COLOR: #0000ff">else</SPAN> <SPAN 
                                style="COLOR: #0000cc">{</SPAN> <SPAN 
                                style="COLOR: #ff9900">/*打开中断硬件的中断能力*/</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outb<SPAN 
                                style="COLOR: #0000cc">(</SPAN>0x10<SPAN 
                                style="COLOR: #0000cc">,</SPAN>short_base<SPAN 
                                style="COLOR: #0000cc">+</SPAN>2<SPAN 
                                style="COLOR: #0000cc">)</SPAN><SPAN 
                                style="COLOR: #0000cc">;</SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN 
                                style="COLOR: #0000cc">}</SPAN><BR><SPAN 
                                style="COLOR: #0000cc">}</SPAN></FONT></SPAN></CODE></P></TD></TR></TBODY></TABLE></P>
                              <DIV>
                              <P>i386 和 x86_64 体系定义了一个函数来查询一个中断线是否可用: 
                              <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 

⌨️ 快捷键说明

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