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

📄 (ldd) ch09-中断处理(下)(转载).htm

📁 html格式
💻 HTM
📖 第 1 页 / 共 4 页
字号:
      color=#ffffff size=3>
      <P><BR>&nbsp;<BR>test_bit(nr,&nbsp;void&nbsp;*addr);<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这个函数是唯一一个不必是原子的为操作;它只是简单地返回该位当前的值。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当这些函数用于访问和修改共享的位时,你只要调用它们即可。而使用位操作来<BR>管理控制共享变量访问的锁变量,则更复杂些,需要举一个例子。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;要访问共享数据项的代码段可以使用set_bit或clear_bit来试着原子地获取锁。<BR>通常是象下面的代码段这样实现的;假定锁位于地址addr的第nr位上。并且假定当锁空<BR>闲时该位为0,锁忙时该位非零。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>/*&nbsp;试着设置锁&nbsp;*/<BR>&nbsp;<BR>while&nbsp;(set_bit(nr,addr)!=0)<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait_for_a_while();<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>/*&nbsp;做你的工作&nbsp;*/<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>/*&nbsp;释放锁,并检查...&nbsp;*/<BR>&nbsp;<BR>if&nbsp;(clear_bit(nr,addr)==0)<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;something_wnt_wrong();&nbsp;/*&nbsp;已经被释放了:出错&nbsp;*/<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这种访问共享数据的方式的毛病是竞争双方都必须要等待。如果其中一方是中断<BR>处理程序,那么这一点就较难保证了。<BR>&nbsp;<BR>原子性的整数操作<BR>内核程序员经常需要在中断处理程序和其它函数间共享整数变量。我们刚才已经看到对<BR>位的原子访问还不足以保证一切都能运行正常(对前面的例子来说,如果一方是一个中断<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>位的原子访问还不足以保证一切都能运行正常(对前面的例子来说,如果一方是一个中断<BR>处理函数的话,那就必须使用cli)。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>实际上,防止竞争条件的需要是如此迫切,以致于内核的开发者为这个问题专门实现了<BR>一个头文件:&lt;asm/atomic.h&gt;。这个头文件比较新,Linux&nbsp;1.2中就没有提供。因此,需<BR>要向后兼容的驱动程序是不能使用的。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>atomic.h中提供的函数比刚才介绍的那些位操作功能更强大。atomic.h中定义了一种新<BR>的数据类型,atomic_t,只能通过原子操作来访问它。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>atomic_t目前在所有支持的体系结构上都被定义为int。下面的操作是为这个数据类型所<BR>定义的,能保证SMP机器上的所有处理器是原子地对它进行访问。这些操作都非常快,因<BR>为它们都尽可能编译成单条的机器指令。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>void&nbsp;atomic_add(atomic_t&nbsp;i,&nbsp;atomic_t&nbsp;*v);<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>void&nbsp;atomic_add(atomic_t&nbsp;i,&nbsp;atomic_t&nbsp;*v);<BR>&nbsp;<BR>将v指向的原子变量加上i。返回值是void类型,大部分时候没有必要知道新值。网络部<BR>分的代码使用这个函数来更新套接字在内存使用上的统计信息。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>void&nbsp;atomic_sub(atomic_t&nbsp;i,&nbsp;atomic_t&nbsp;*v);<BR>&nbsp;<BR>从*v里减去i。在最新的2.1版的内核中这两个函数的参数i都声明成int类型,但这种改<BR>变主要是出于美观的需要,并不对源代码造成影响。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>void&nbsp;atomic_inc(atomic_t&nbsp;*v);<BR>&nbsp;<BR>void&nbsp;atomic_dec(atomic_t&nbsp;*v);<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对原子变量加减1。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>int&nbsp;atomic_dec_and_test(atomic_t&nbsp;*v);<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>int&nbsp;atomic_dec_and_test(atomic_t&nbsp;*v);<BR>&nbsp;<BR>该函数是在1.3.84版的内核里加入的,用于跟踪引用计数。仅当变量*v在减1后取值为0<BR>时返回值为0。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>如上所述,只能使用上面这些函数来访问atomic_t类型的数据。如果你将原子数据项传<BR>递给了一个要求参数类型为整型的函数,编译时就会得到警告。不用说,可以读取原子<BR>数据项的当前值并将它强制转换成其它数据类型。<BR>&nbsp;<BR>无竞争地进入睡眠<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在讨论进入睡眠的问题中我们曾忽略了一个竞争条件。这个问题实际上要比中断<BR>驱动的I/O问题更普遍,而有效的解决方案需要对sleep_on的实现内幕有些了解。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这种特别的竞争条件发生在检查进入睡眠的条件和对sleep_on的实际调用之间。<BR>下面的测试代码和前面使用的代码是一样的,但我觉得还是值得再在这里列出:<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>while&nbsp;(short_head==short_tail){<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>while&nbsp;(short_head==short_tail){<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interruptible_sleep_on(&amp;short_queue);<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;...&nbsp;*/<BR>&nbsp;<BR>}<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果要安全地进行比较和进入睡眠,你必须先禁止中断报告,然后测试条件并进<BR>入睡眠。因此,比较中被测试的变量不会被修改。内核允许进程在发出cli指令后就进入<BR>睡眠。而在将进程插入它的等待队列之后,在调用shcedule之前,内核只要简单地重新<BR>打开中断报告就可以了。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里给出的例子代码使用了while循环,由该循环来进行信号处理。如果有阻塞<BR>的信号向进程发出报告,interruptible_sleep_on就返回,再次进行while语句中的测试<BR>。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是一种可能的实现:<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>while&nbsp;(short_head==short_tail){<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cli();<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(short_head==short_tail)<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interuptible_sleep_on(&amp;short_queue);<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sti();<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;...&nbsp;信号解码&nbsp;....&nbsp;*/<BR>&nbsp;<BR>}<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果中断是在cli后发生的,那么这个中断在当前进程进入睡眠前都会处于待处<BR>理状态。而当中断最终报告给处理器时,进程已经进入了睡眠,可以被安全地唤醒。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>理状态。而当中断最终报告给处理器时,进程已经进入了睡眠,可以被安全地唤醒。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在这个例子中,我可以使用cli/sti,是因为设计的这段范例代码存在于read方<BR>法内的;否则我们必须使用更为安全的save_flags,cli,和restore_flags函数。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果在进入睡眠之前你不想禁止中断,那么还有另一种方法来完成与上面相同的<BR>任务(Linus非常喜欢用这种方法)。但是,如果你愿意的话你可以跳过下面的讨论,因为<BR>下面的讨论的确有点太细了。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该方法的基本想法是,进程可以把自己排进等待队列,声明自己的状态为睡眠状<BR>态,然后执行它的测试代码。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>典型的实现如下:<BR>&nbsp;<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>&nbsp;<BR>struct&nbsp;wait_queue&nbsp;wait&nbsp;=&nbsp;{current,&nbsp;NULL};<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>add_wait(&amp;short_queue,&nbsp;&amp;wait);<BR>&nbsp;<BR>current-&gt;state=TASK_INTERRUPTIBLE;<BR>&nbsp;<BR>while&nbsp;(short_head==short_tail){<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;schedule();<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;...&nbsp;信号解码&nbsp;...&nbsp;*/<BR>&nbsp;<BR>}<BR>&nbsp;<BR>remove_wait_queue(&amp;short_queue,&nbsp;&amp;wait);<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这段代码看起来有点象将sleep_on的内部实现展开了。显式地声明了wait变量,<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这段代码看起来有点象将sleep_on的内部实现展开了。显式地声明了wait变量,<BR>因为需要用它来使进程进入睡眠;这一切是在第5章的“等待队列”一节中解释的,但这<BR>个例子中引入了一些新的符号。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>current-&gt;state<BR>&nbsp;<BR>这个字段是给调度器用的提示。调度器被激活后,它将通过观察所有进程的state字段来<BR>决定接着作些什么。所有进程都可以任意修改自己的state字段,但在调度器运行之前这<BR>种改变还不会生效。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>#include&nbsp;&lt;linux/sched.h&gt;<BR>&nbsp;<BR>TASK_RUNNING<BR>&nbsp;<BR>TASK_INTERRUPTIBLE<BR>&nbsp;<BR>TASK_UNINTERRUPTIBLE<BR>&nbsp;<BR>这些符号名代表了current-&gt;state最经常取的一些值。TASK_RUNNING表示进程正在运行<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>这些符号名代表了current-&gt;state最经常取的一些值。TASK_RUNNING表示进程正在运行<BR>,其它两个表示进程正在睡眠。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>void&nbsp;add_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>void&nbsp;remove_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>void&nbsp;__add_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>void&nbsp;__&nbsp;remove_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>这些函数用于从等待队列中插入和删除进程。wait参数必须指向进程堆栈所在的页(临时<BR>变量)。以下划线开头的函数运行的更快些,但它们在禁止中断后才能被调用(例如,在<BR>快速中断处理程序内)。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有了这些背景知识,下面让我们看看当中断到达时会发生什么。此时处理程序将<BR>调用wake_up_interruptible(&amp;short_queue);对Linux而言,这意味着“将state置为TA<BR>SK_RUNNING”。因此,如果在while条件和schedule调用间有中断报告的话,该任务的st<BR>ate字段将会又被标记为TASK_RUNNING的,因此不会丢失数据。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>ate字段将会又被标记为TASK_RUNNING的,因此不会丢失数据。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;而如果进程仍是“可中断的”(TASK_INTERRUPTIBLE),schedule将保持它的睡眠<BR>状态。<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;值得注意的是,wake_up系统调用并不会将进程从等待队列中删去。是由sleep_o<BR>n来对等待队列进行进程的添加和删除的。因此程序代码必须显式地调用add_wait_queue<BR>和remove_wait_queue,因为这种情况下不再使用sleep_on了。<BR>&nbsp;<BR>中断处理的版本相关性<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不是所有本章引入的代码都能向后兼容地移植到Linux&nbsp;1.2上的。在此我将列出<BR>主要的差异并对如何处理这些差异提出建议。实际上,short在2.0.x和1.2.13版的内核<BR>上都编译和运行得很好。<BR>&nbsp;<BR>request_irq函数的不同原型<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我在这一整章中使用的给request_irq函数传递参数的方式都是到1.3.70版的内<BR>核才引入的,因为是到这个版本才出现了共享中断处理程序的。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;更早的内核版本并不需要dev_id参数,原型也相对简单些:<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;更早的内核版本并不需要dev_id参数,原型也相对简单些:<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>int&nbsp;request_irq(unsigned&nbsp;int&nbsp;irq,<BR>&nbsp;<BR>void&nbsp;(*handler)(int,&nbsp;struct&nbsp;pt_regs&nbsp;*),<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;flags,&nbsp;const&nbsp;char&nbsp;*device);<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;只要使用下面的宏定义(注意早期的版本中free_irq也没有dev_id参数),新的语<BR>义可以很容易地强加在旧原型上:<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>#if&nbsp;LINUX_VERSION_CODE&nbsp;&lt;&nbsp;VERSION_CODE(1,3,70)<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;预处理器必须能处理递归的定义&nbsp;*/<BR>&nbsp;<BR>#&nbsp;&nbsp;define&nbsp;request_irq(irq,fun,fla,nam,dev)&nbsp;request_irq(irq,fun,fla,nam)<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>#&nbsp;&nbsp;define&nbsp;free_irq(irq,dev)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free_irq(irq)<BR>&nbsp;<BR>#endif<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这些宏只是简单地丢弃额外的dev参数。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;处理函数原型上的差异通过显式的#if/#else/#endif语句得到很好的处理。如果<BR>你使用了dev_id指针,旧内核的条件分支可以将它申明为NULL变量,这样处理函数体就<BR>可以对NULL设备指针进行处理了。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;short模块中的一个例子可以作为这种想法的范例:<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>#if&nbsp;LINUX_VERSION_CODE&nbsp;&lt;&nbsp;VERSION_CODE(1,3,70)<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>void&nbsp;short_sh_interrupt(int&nbsp;irq,&nbsp;struct&nbsp;pt_regs&nbsp;*regs)<BR>&nbsp;<BR>{<BR>&nbsp;<BR>&nbsp;void&nbsp;*dev_id&nbsp;=&nbsp;NULL;<BR>&nbsp;<BR>#else<BR>&nbsp;<BR>void&nbsp;short_sh_interrupt(int&nbsp;irq,&nbsp;void&nbsp;*dev_id,&nbsp;struct&nbsp;pt_regs&nbsp;*regs)<BR>&nbsp;<BR>{<BR>&nbsp;<BR>#endif<BR>&nbsp;<BR>探测中断信号线<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;内核到1.3.30版开始开放探测函数。如果你希望你的驱动程序能移植到旧的内核<BR>上,你将不得不实现DIY检测。实际上早在1.2版的内核,这些函数就已经存在了,只是<BR>模块化的驱动程序无法使用罢了。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这样,移植中断处理函数就没有什么其它的问题了。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这样,移植中断处理函数就没有什么其它的问题了。<BR>&nbsp;<BR>快速参考<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本章引入了下面这些与中断管理有关的符号:<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>#include&nbsp;&lt;linux/sched.h&gt;<BR>&nbsp;<BR>int&nbsp;request_irq(unsigned&nbsp;int&nbsp;irq,&nbsp;void&nbsp;(*handler)());<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;flags,&nbsp;const&nbsp;char&nbsp;*device,&nbsp;void&nbsp;*dev_id);<BR>&nbsp;<BR>void&nbsp;free_irq(unsigned&nbsp;int&nbsp;irq,&nbsp;void&nbsp;*dev_id);<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这些系统调用用于注册和注销中断处理程序。低于2.0版的内核不提供dev_id参<BR>数。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>SA_INTERRUPT<BR>&nbsp;<BR>SA_SHIRQ<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>SA_SHIRQ<BR>&nbsp;<BR>SA_SAMPLE_RANDOM<BR>&nbsp;<BR>这些是request_irq函数的各种选项。SA_INTERRUPT请求安装快速中断处理程序(相对于<BR>慢速处理函数)。SA_SHIRQ安装共享中断处理函数,而第三种选项表明产生的中断的时间<BR>戳对系统熵池(entropy&nbsp;pool)有贡献。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>/proc/interrupts<BR>&nbsp;<BR>/proc/stat<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这些文件系统节点用于报告关于硬件中断和安装的处理函数的信息。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;probe_irq_on(void);<BR>&nbsp;<BR>int&nbsp;probe_irq_off(unsigned&nbsp;long);<BR>&nbsp;<BR>当驱动程序需要探测设备使用哪根中断信号线时,可以使用这些函数。在中断产生之后<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>当驱动程序需要探测设备使用哪根中断信号线时,可以使用这些函数。在中断产生之后<BR>,probe_irq_on的返回值必须传回给probe_irq_off。probe_irq_off的返回值就是检测<BR>到的中断号。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>void&nbsp;disable_irq(int&nbsp;irq);<BR>&nbsp;<BR>void&nbsp;enable_irq(int&nbsp;irq);<BR>&nbsp;<BR>驱动程序可以启动和禁止中断报告。禁止中断后,硬件产生的中断都将丢失。在上半部<BR>处理程序中调用这些函数则没有任何效果。而使用共享中断处理程序的驱动程序决不能<BR>使用这些函数。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>#include&nbsp;&lt;linux/interrupt.h&gt;<BR>&nbsp;<BR>void&nbsp;mark_bh(int&nbsp;nr);<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这些函数用于标记要执行的下半部。<BR>&nbsp;<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>&nbsp;<BR>#include&nbsp;&lt;asm/bitops.h&gt;<BR>&nbsp;<BR>set_bit(nr,&nbsp;void&nbsp;*addr);<BR>&nbsp;<BR>clear_bit(nr,&nbsp;void&nbsp;*addr);<BR>&nbsp;<BR>change_bit(nr,&nbsp;void&nbsp;*addr);<BR>&nbsp;<BR>test_bit(nr,&nbsp;void&nbsp;*addr);<BR>&nbsp;<BR>这些函数用于原子性地访问位的值;它们可作用于标志位和锁变量。使用这些函数避免<BR>了所有与对位的并发访问有关的竞争条件。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>#include&nbsp;&lt;asm/atomic.h&gt;<BR>&nbsp;<BR>typedef&nbsp;int&nbsp;atomic_t;<BR>&nbsp;<BR>void&nbsp;atomic_add(atomic_t&nbsp;i,&nbsp;atomic_t&nbsp;*v);<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>void&nbsp;atomic_sub(atomic_t&nbsp;i,&nbsp;atomic_t&nbsp;*v);<BR>&nbsp;<BR>void&nbsp;atomic_inc(atomic_t&nbsp;*v);<BR>&nbsp;<BR>void&nbsp;atomic_dec(atomic_t&nbsp;*v);<BR>&nbsp;<BR>int&nbsp;atomic_dec_and_test(atomic_t&nbsp;*v);<BR>&nbsp;<BR>这些函数用于原子地访问整数变量。如果想让编译时不出现警告信息,必须只使用这些<BR>函数来访问atomic_t类型的变量。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>#include&nbsp;&lt;linux/sched.h&gt;<BR>&nbsp;<BR>TASK_RUNNING<BR>&nbsp;<BR>TASK_INTERRUPTIBLE<BR>&nbsp;<BR>TASK_UNINTERRUPTIBLE<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这些是current-&gt;state最经常取的一些值。它们是给schedule用的提示。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这些是current-&gt;state最经常取的一些值。它们是给schedule用的提示。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>void&nbsp;add_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>void&nbsp;remove_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>void&nbsp;__add_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>void&nbsp;__&nbsp;remove_wait_queue(struct&nbsp;wait_queue&nbsp;**&nbsp;p,&nbsp;struct&nbsp;wait_queue&nbsp;*wait)<BR>&nbsp;<BR>这些是使用等待队列的最底层的函数。打头的下划线标志该函数是底层的函数,使用后<BR>两个函数时处理器必须已经禁止了中断报告。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>-----------------------------------------------------------------------------<BR>&nbsp;<BR>*&nbsp;PC机通常就已经有了两个中断控制芯片,叫做8259芯片(主从片)。而可编程的中断控<BR>制器设备已经不存在了,但现代的芯片组中也实现了相同的功能。<BR>&nbsp;<BR>*&nbsp;shortint设备是通过交替地向并口写入0x00和0xff来实现的。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>*&nbsp;PC机通常就已经有了两个中断控制芯片,叫做8259芯片(主从片)。而可编程的中断控<BR>制器设备已经不存在了,但现代的芯片组中也实现了相同的功能。<BR>&nbsp;<BR>*&nbsp;shortint设备是通过交替地向并口写入0x00和0xff来实现的。<BR>&nbsp;<BR>*&nbsp;随后就会介绍,使用自己的下半部的驱动程序可以调用disable_bh函数。<BR>&nbsp;<BR>--<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.-.<BR>&nbsp;<BR>--<BR><FONT 
      color=#00ff00>※&nbsp;来源:.华南网木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;202.38.196.234]</FONT><BR>--<BR><FONT 
      color=#00ffff>※&nbsp;转寄:.华南网木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#0000ff>※&nbsp;转寄:.华南网木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#ffff00>※&nbsp;转载:.南京大学小百合站&nbsp;bbs.nju.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#ff0000>※&nbsp;转载:·饮水思源&nbsp;bbs.sjtu.edu.cn·[FROM:&nbsp;211.80.41.106]</FONT><BR></P></FONT>
      <P align=center><A href="http://joyfire.net/lsdp/index.htm"><FONT 
      color=#ffffff size=2>目录页</FONT></A> | <A 
      href="http://joyfire.net/lsdp/11.htm"><FONT color=#ffffff 
      size=2>上一页</FONT></A> | <A href="http://joyfire.net/lsdp/13.htm"><FONT 

⌨️ 快捷键说明

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