[ZLG-ARM] softirq,tasklet和workqueue的分析

[复制链接]
3081|3
 楼主| billen 发表于 2009-6-4 16:29 | 显示全部楼层 |阅读模式
softirq,tasklet和workqueue的分析<br /><br />creator<br /><br />sz111@126.com<br /><br />creatorwu.cublog.cn<br /><br /><br />今天看了《深入理解Linux内核》的中断和异常一章,对Softirq,tasklet和workqueue做一个简单的总结和分析。<br /><br />其实softirq和taskled都属于软中断,而工作队列是和软中断无关,仅仅是内核中的一个内核线程在等待工作任务,工作队列可以发送工作任务。不过他们还是有个共同点,就是都有延后执行的作用。<br /><br />1.首先看&nbsp;do_softirq如何被调用和如何处理。<br /><br />#ifdef&nbsp;__ARCH_IRQ_EXIT_IRQS_DISABLED<br /><br />#&nbsp;define&nbsp;invoke_softirq()&nbsp;__do_softirq()<br /><br />#else<br /><br />#&nbsp;define&nbsp;invoke_softirq()&nbsp;do_softirq()<br /><br />#endif<br /><br />/*<br /><br />Exit&nbsp;an&nbsp;interrupt&nbsp;context.&nbsp;Process&nbsp;softirqs&nbsp;if&nbsp;needed&nbsp;and&nbsp;possible<br /><br />当从硬件中断退出的时候,会调用&nbsp;invoke_softirq,其实也就是do_softirq(),不过arm是__do_softirq().这个在下面分析。<br /><br />*/<br /><br />void&nbsp;irq_exit(void)<br /><br />{<br /><br />account_system_vtime(current);<br /><br />trace_hardirq_exit();<br /><br />sub_preempt_count(IRQ_EXIT_OFFSET);<br /><br />/*<br /><br />判断当前是否有硬件中断嵌套,并且软件中断是否处在pending状态,<br /><br />in_interrupt:#define&nbsp;irq_count()&nbsp;(preempt_count()&nbsp;&&nbsp;(HARDIRQ_MASK&nbsp;|&nbsp;SOFTIRQ_MASK))<br /><br />如果等于0说明是允许抢占。非0不允许。<br /><br />注意:必须同时满足不在嵌套同时软件中断有pending(即:安装了软件处理)<br /><br />*/<br /><br />if&nbsp;(!in_interrupt()&nbsp;&&&nbsp;local_softirq_pending())<br /><br />invoke_softirq();<br /><br /><br /><br /><br />#ifdef&nbsp;CONFIG_NO_HZ<br /><br />/*&nbsp;Make&nbsp;sure&nbsp;that&nbsp;timer&nbsp;wheel&nbsp;updates&nbsp;are&nbsp;propagated&nbsp;*/<br /><br />if&nbsp;(!in_interrupt()&nbsp;&&&nbsp;idle_cpu(smp_processor_id())&nbsp;&&&nbsp;!need_resched())<br /><br />tick_nohz_stop_sched_tick();<br /><br />rcu_irq_exit();<br /><br />#endif<br /><br />preempt_enable_no_resched();<br /><br />}<br /><br /><br /><br /><br />asmlinkage&nbsp;void&nbsp;do_softirq(void)<br /><br />{<br /><br />__u32&nbsp;pending;<br /><br />unsigned&nbsp;long&nbsp;flags;<br /><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;入口判断主要是为了与&nbsp;ksoftirqd&nbsp;互斥。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />if&nbsp;(in_interrupt())<br /><br />return;<br /><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local_irq_save(flags);&nbsp;&nbsp;&nbsp;&nbsp;//判断是否有softirq&nbsp;pending<br />pending&nbsp;=&nbsp;local_softirq_pending();<br /><br />//如果有就进行真正的处理<br /><br />if&nbsp;(pending)&nbsp;{<br /><br />__do_softirq();<br /><br />}<br /><br />local_irq_restore(flags);<br /><br />}<br /><br />/*<br /><br />*&nbsp;We&nbsp;restart&nbsp;softirq&nbsp;processing&nbsp;MAX_SOFTIRQ_RESTART&nbsp;times,<br /><br />*&nbsp;and&nbsp;we&nbsp;fall&nbsp;back&nbsp;to&nbsp;softirqd&nbsp;after&nbsp;that.<br /><br />*<br /><br />*&nbsp;This&nbsp;number&nbsp;has&nbsp;been&nbsp;established&nbsp;via&nbsp;experimentation.<br /><br />*&nbsp;The&nbsp;two&nbsp;things&nbsp;to&nbsp;balance&nbsp;is&nbsp;latency&nbsp;against&nbsp;fairness&nbsp;-<br /><br />*&nbsp;we&nbsp;want&nbsp;to&nbsp;handle&nbsp;softirqs&nbsp;as&nbsp;soon&nbsp;as&nbsp;possible,&nbsp;but&nbsp;they<br /><br />*&nbsp;should&nbsp;not&nbsp;be&nbsp;able&nbsp;to&nbsp;lock&nbsp;up&nbsp;the&nbsp;box.<br /><br />*/<br /><br />//定义最大的软中断调用次数<br /><br />#define&nbsp;MAX_SOFTIRQ_RESTART&nbsp;10<br /><br /><br /><br /><br />asmlinkage&nbsp;void&nbsp;__do_softirq(void)<br /><br />{<br /><br />struct&nbsp;softirq_action&nbsp;*h;<br /><br />__u32&nbsp;pending;<br /><br />int&nbsp;max_restart&nbsp;=&nbsp;MAX_SOFTIRQ_RESTART;<br /><br />int&nbsp;cpu;<br /><br />//判断是否有softirq&nbsp;pending<br /><br />pending&nbsp;=&nbsp;local_softirq_pending();<br /><br />account_system_vtime(current);<br /><br />//屏蔽其他软中断,所以软中断仅仅能一个在执行。<br /><br />//static&nbsp;inline&nbsp;void&nbsp;__local_bh_disable(unsigned&nbsp;long&nbsp;ip)<br /><br />//{<br /><br />//add_preempt_count(SOFTIRQ_OFFSET);这个知道吧,还记得刚才&nbsp;in_interrupt的判断吧。<br /><br />//barrier();<br /><br />//}<br /><br />__local_bh_disable((unsigned&nbsp;long)__builtin_return_address(0));<br /><br />trace_softirq_enter();<br /><br /><br /><br /><br />cpu&nbsp;=&nbsp;smp_processor_id();<br /><br />restart:<br /><br />/*&nbsp;Reset&nbsp;the&nbsp;pending&nbsp;bitmask&nbsp;before&nbsp;enabling&nbsp;irqs&nbsp;*/<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;每次循环在允许硬件&nbsp;ISR&nbsp;强占前,首先重置软中断&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;的标志位。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />set_softirq_pending(0);<br /><br /><br /><br /><br />local_irq_enable();//开中断<br /><br />//static&nbsp;struct&nbsp;softirq_action&nbsp;softirq_vec[32]&nbsp;定义在此,为32,其实真正用到的仅仅6个。<br /><br />//当然,后续Linux版本有新加入<br /><br />//HI_SOFTIRQ=0,<br /><br />//TIMER_SOFTIRQ,<br /><br />//NET_TX_SOFTIRQ,<br /><br />//NET_RX_SOFTIRQ,<br /><br />//BLOCK_SOFTIRQ,<br /><br />//TASKLET_SOFTIRQ,<br /><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;ISR&nbsp;执行完成后,它的所注册的软中断无法马上运行,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;别忘了,现在虽是开硬件中断执行,但前面的&nbsp;__local_bh_disable()&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;__local_bh_disable()&nbsp;函数设置了一个标志当作互斥量,而这个&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;标志正是上面的&nbsp;irq_exit()&nbsp;和&nbsp;do_softirq()&nbsp;函数中的&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;in_interrupt()&nbsp;函数判断的条件之一,也就是说&nbsp;in_interrupt()&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;MAX_SOFTIRQ_RESTART)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;才可能处理到这个时候触发的硬件中断所注册的软中断。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<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;&nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;=&nbsp;softirq_vec;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;循环处理所有&nbsp;softirq&nbsp;软中断注册函数。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />do&nbsp;{<br /><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;&nbsp;&nbsp;&nbsp;//&nbsp;如果对应的软中断设置&nbsp;pending&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(pending&nbsp;&&nbsp;1)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;在这里执行了这个软中断所注册的回调函数<br />h-&gtaction(h);<br /><br />rcu_bh_qsctr_inc(cpu);<br /><br />}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;继续找,直到把软中断向量表中所有&nbsp;pending&nbsp;的软&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;中断处理完成。<br />H++;<br /><br />//&nbsp;从代码里可以看出按位操作,表明一次循环只<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;处理&nbsp;32&nbsp;个软中断的回调函数<br />pending&nbsp;&gt&gt=&nbsp;1;<br /><br />}&nbsp;while&nbsp;(pending);<br /><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />local_irq_disable();<br /><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;&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;restart&nbsp;处重复执行。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />pending&nbsp;=&nbsp;local_softirq_pending();<br /><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;pending&nbsp;位,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;但在当前一直屏蔽软中断的环境下无法得到执行,前面提&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;到过,因为&nbsp;irq_exit()&nbsp;和&nbsp;do_softirq()&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;&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;ISR&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;没有到&nbsp;10&nbsp;次的话,那么则跳转到&nbsp;restart&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;//<br /><br /><br /><br />if&nbsp;(pending&nbsp;&&&nbsp;--max_restart)<br /><br />goto&nbsp;restart;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;如果以上步骤重复了&nbsp;10&nbsp;次后还有&nbsp;pending&nbsp;的软中断的话,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;那么系统在一定时间内可能达到了一个峰值,为了平衡这点。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;系统专门建立了一个&nbsp;ksoftirqd&nbsp;线程来处理,这样避免在一&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;定时间内负荷太大。这个&nbsp;ksoftirqd&nbsp;线程本身是一个大循环,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;在某些条件下为了不负载过重,它是可以被其他进程抢占的,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;但注意,它是显示的调用了&nbsp;preempt_xxx()&nbsp;和&nbsp;schedule()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;才会被抢占和切换的。这么做的原因是因为在它一旦调用&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;local_softirq_pending()&nbsp;函数检测到有&nbsp;pending&nbsp;的软中断&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;需要处理的时候,则会显示的调用&nbsp;do_softirq()&nbsp;来处理软中&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;断。也就是说,下面代码唤醒的&nbsp;ksoftirqd&nbsp;线程有可能会回&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;到这个函数当中来,尤其是在系统需要响应很多软中断的情况&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;下,它的调用入口是&nbsp;do_softirq(),这也就是为什么在&nbsp;do_softirq()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;的入口处也会用&nbsp;in_interrupt()&nbsp;&nbsp;函数来判断是否有软中断&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;正在处理的原因了,目的还是为了防止重入。ksoftirqd&nbsp;实现&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;看下面对&nbsp;ksoftirqd()&nbsp;函数的分析。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br /><br /><br /><br />if&nbsp;(pending)<br /><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;&nbsp;//&nbsp;此函数实际是调用&nbsp;wake_up_process()&nbsp;来唤醒&nbsp;ksoftirqd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;<br />wakeup_softirqd();<br /><br /><br /><br /><br />trace_softirq_exit();<br /><br /><br /><br /><br />account_system_vtime(current);<br /><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;local_bh_enable(),不会再次触发&nbsp;do_softirq()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;的调用。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;<br />_local_bh_enable();<br /><br />}<br /><br /><br /><br /><br />static&nbsp;int&nbsp;ksoftirqd(void&nbsp;*&nbsp;__bind_cpu){&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_user_nice(current,&nbsp;19);&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;&nbsp;&nbsp;&nbsp;&nbsp;current-&gtflags&nbsp;|=&nbsp;PF_NOFREEZE;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_current_state(TASK_INTERRUPTIBLE);&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;pending&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;while&nbsp;(!kthread_should_stop())&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;&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;&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;preempt_disable();&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;&nbsp;&nbsp;&nbsp;//&nbsp;首先判断系统当前没有需要处理的&nbsp;pending&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!local_softirq_pending())&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;没有的话在主动放弃&nbsp;CPU&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preempt_enable_no_resched();&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;显示调用此函数主动放弃&nbsp;CPU&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;schedule();&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;注意:如果当前显示调用&nbsp;schedule()&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;话,将会执行下面的&nbsp;preempt_disable()&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;&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;&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;&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;&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;&nbsp;&nbsp;preempt_disable();&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;&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;&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;pending&nbsp;的软中断需要执行时。二是进入循环时&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;没有&nbsp;pending&nbsp;的软中断,当前进程再次被调度获得&nbsp;CPU&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__set_current_state(TASK_RUNNING);&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;&nbsp;&nbsp;&nbsp;//&nbsp;循环判断是否有&nbsp;pending&nbsp;的软中断,如果有则调用&nbsp;do_softirq()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;来做具体处理。注意:这里又是一个&nbsp;do_softirq()&nbsp;的入口点,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;那么在&nbsp;__do_softirq()&nbsp;当中循环处理&nbsp;10&nbsp;次软中断的回调函数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;后,如果还有&nbsp;pending&nbsp;的话,会又调用到这里。那么在这里则&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;又会有可能去调用&nbsp;__do_softirq()&nbsp;来处理软中断回调函数。在前&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;面介绍&nbsp;__do_softirq()&nbsp;时已经提到过,处理&nbsp;10&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;系统非常繁忙时,这个进程将会与&nbsp;do_softirq()&nbsp;相互交替执行,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;这时此进程占用&nbsp;CPU&nbsp;应该会很高,虽然下面的&nbsp;cond_resched()&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;因被调度而减少&nbsp;CPU&nbsp;负荷,但是在非常繁忙时这个进程仍然有可&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;能大量占用&nbsp;CPU。&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;&nbsp;&nbsp;&nbsp;while&nbsp;(local_softirq_pending())&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;Preempt&nbsp;disable&nbsp;stops&nbsp;cpu&nbsp;going&nbsp;offline.&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;If&nbsp;already&nbsp;offline,&nbsp;we'll&nbsp;be&nbsp;on&nbsp;wrong&nbsp;CPU:&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;don't&nbsp;process&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;if&nbsp;(cpu_is_offline((long)__bind_cpu))&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;如果当前被关联的&nbsp;CPU&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;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;到&nbsp;wait_to_die&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto&nbsp;wait_to_die;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;执行&nbsp;do_softirq()&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;返回,还记得前面介绍的&nbsp;in_interrupt()&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_softirq();&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preempt_enable_no_resched();&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;这个函数有可能间接的调用&nbsp;schedule()&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;超标的情况下不至于让这个进程长时间大量的占用&nbsp;CPU,&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cond_resched();&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preempt_disable();&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;&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;&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;&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;&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;&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;preempt_enable();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_current_state(TASK_INTERRUPTIBLE);&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;调度器会根据优先级来使当前进程运行。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__set_current_state(TASK_RUNNING);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;////&nbsp;一直等待到当前进程被停止//wait_to_die:&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;&nbsp;&nbsp;&nbsp;&nbsp;preempt_enable();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Wait&nbsp;for&nbsp;kthread_stop&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_current_state(TASK_INTERRUPTIBLE);&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;CPU&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(!kthread_should_stop())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;schedule();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_current_state(TASK_INTERRUPTIBLE);&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;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;调度器会根据优先级来使当前进程运行。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__set_current_state(TASK_RUNNING);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;}<br />2.再来看tasklet如何被调用和如何处理。<br /><br />tasklet主要是I/O驱动程序中实现可延迟函数的首选方法。tasklet是建立在HI_SOFTIRQ和TASKLET_SOFTIRQ软中断之上。几个tasklet可以同时与一个软中断关联,<br /><br />每个tasklet执行自己的函数。<br /><br />tasklet和高优先级的tasklet分别存放在tasklet_vec和tasklet_hi_vec数组中。<br /><br />struct&nbsp;tasklet_struct<br /><br />{<br /><br />struct&nbsp;tasklet_struct&nbsp;*next;<br /><br />unsigned&nbsp;long&nbsp;state;<br /><br />atomic_t&nbsp;count;<br /><br />void&nbsp;(*func)(unsigned&nbsp;long);<br /><br />unsigned&nbsp;long&nbsp;data;<br /><br />};<br /><br />static&nbsp;void&nbsp;tasklet_action(struct&nbsp;softirq_action&nbsp;*a)<br /><br />{<br /><br />struct&nbsp;tasklet_struct&nbsp;*list;<br /><br />//禁止本地中断<br /><br />local_irq_disable();<br /><br />//把tasklet_vec[n](n为cpu号)指向的链表的地址存入局部变量list<br /><br />list&nbsp;=&nbsp;__get_cpu_var(tasklet_vec).list;<br /><br />//把tasklet_vec[n](n为cpu号)的值设定为NULL,因此已经调度的tasklet描述符的链表被清空。<br /><br />__get_cpu_var(tasklet_vec).list&nbsp;=&nbsp;NULL;<br /><br />//打开中断<br /><br />local_irq_enable();<br /><br /><br /><br /><br />while&nbsp;(list)&nbsp;{<br /><br />struct&nbsp;tasklet_struct&nbsp;*t&nbsp;=&nbsp;list;<br /><br /><br /><br /><br />list&nbsp;=&nbsp;list-&gtnext;<br /><br />//查看count字段,检查tasklet是否被禁止,如果是,就清&nbsp;TASKLET_STATE_SCHED<br /><br />//同时执行tasklet函数<br /><br />if&nbsp;(tasklet_trylock(t))&nbsp;{<br /><br />if&nbsp;(!atomic_read(&t-&gtcount))&nbsp;{<br /><br />if&nbsp;(!test_and_clear_bit(TASKLET_STATE_SCHED,&nbsp;&t-&gtstate))<br /><br />BUG();<br /><br />t-&gtfunc(t-&gtdata);<br /><br />tasklet_unlock(t);<br /><br />continue;<br /><br />}<br /><br />tasklet_unlock(t);<br /><br />}<br /><br /><br /><br /><br />local_irq_disable();<br /><br />t-&gtnext&nbsp;=&nbsp;__get_cpu_var(tasklet_vec).list;<br /><br />__get_cpu_var(tasklet_vec).list&nbsp;=&nbsp;t;<br /><br />__raise_softirq_irqoff(TASKLET_SOFTIRQ);<br /><br />local_irq_enable();<br /><br />}<br /><br />}<br /><br />3.最后是看workqueue处理。<br /><br />工作队列其实比较单纯,并不在中断的上下文进行处理,是在进程上下文进行处理的,这点非常重要。很多情况需要在进程上下文进行处理的。因为中断上下文不可以做进程切换。工作队列里面的函数是通过内核线程来执行的。<br /><br />主要的一个数据结构struct&nbsp;workqueue_struct,它包含了&nbsp;cpu_workqueue_struct&nbsp;如下:<br /><br />/*<br /><br />*&nbsp;The&nbsp;per-CPU&nbsp;workqueue&nbsp;(if&nbsp;single&nbsp;thread,&nbsp;we&nbsp;always&nbsp;use&nbsp;the&nbsp;first<br /><br />*&nbsp;possible&nbsp;cpu).<br /><br />*/<br /><br />struct&nbsp;cpu_workqueue_struct&nbsp;{<br /><br /><br /><br /><br />spinlock_t&nbsp;lock;//保护数据的lock<br /><br />struct&nbsp;list_head&nbsp;worklist;//挂起链表的头结点,集中了工作队列中所有挂起函数。<br /><br />wait_queue_head_t&nbsp;more_work;//等待队列,其中的工作者线程因为等待工作而处于休眠<br /><br />struct&nbsp;work_struct&nbsp;*current_work;//等待队列,其中的进程由于等待工作队列被刷新而处于休眠。<br /><br />struct&nbsp;workqueue_struct&nbsp;*wq;//指向workqueue_struct&nbsp;结构的指针。<br /><br />struct&nbsp;task_struct&nbsp;*thread;//指向工作者线程的描述符。<br /><br /><br /><br /><br />int&nbsp;run_depth;&nbsp;/*&nbsp;Detect&nbsp;run_workqueue()&nbsp;recursion&nbsp;depth&nbsp;*/<br /><br />}&nbsp;____cacheline_aligned;<br /><br /><br /><br /><br />struct&nbsp;work_struct&nbsp;{<br /><br />atomic_long_t&nbsp;data;&nbsp;//传给挂起函数的参数,是个指针。<br /><br />#define&nbsp;WORK_STRUCT_PENDING&nbsp;0&nbsp;/*&nbsp;T&nbsp;if&nbsp;work&nbsp;item&nbsp;pending&nbsp;execution&nbsp;*/<br /><br />#define&nbsp;WORK_STRUCT_FLAG_MASK&nbsp;(3UL)<br /><br />#define&nbsp;WORK_STRUCT_WQ_DATA_MASK&nbsp;(~WORK_STRUCT_FLAG_MASK)<br /><br />struct&nbsp;list_head&nbsp;entry;&nbsp;//如果函数已经在工作队列链表中,它为1,否则为0<br /><br />work_func_t&nbsp;func;&nbsp;//挂起函数的指针<br /><br />#ifdef&nbsp;CONFIG_LOCKDEP<br /><br />struct&nbsp;lockdep_map&nbsp;lockdep_map;<br /><br />#endif<br /><br />};<br /><br /><br />创建一个工作队列create_workqueue.<br /><br />把函数插入工作队列:queue_work,它同时会唤醒内核线程(worker_thread)<br /><br />//内核线程是一直在执行的。<br /><br />static&nbsp;int&nbsp;worker_thread(void&nbsp;*__cwq)<br /><br />{<br /><br />struct&nbsp;cpu_workqueue_struct&nbsp;*cwq&nbsp;=&nbsp;__cwq;<br /><br />DEFINE_WAIT(wait);<br /><br /><br /><br /><br />if&nbsp;(cwq-&gtwq-&gtfreezeable)<br /><br />set_freezable();<br /><br /><br /><br /><br />set_user_nice(current,&nbsp;-5);<br /><br /><br /><br /><br />for&nbsp;(;;)&nbsp;{<br /><br />prepare_to_wait(&cwq-&gtmore_work,&nbsp;&wait,&nbsp;TASK_INTERRUPTIBLE);<br /><br />if&nbsp;(!freezing(current)&nbsp;&&<br /><br />!kthread_should_stop()&nbsp;&&<br /><br />list_empty(&cwq-&gtworklist))<br /><br />schedule();<br /><br />finish_wait(&cwq-&gtmore_work,&nbsp;&wait);<br /><br /><br /><br /><br />try_to_freeze();<br /><br /><br /><br /><br />if&nbsp;(kthread_should_stop())<br /><br />break;<br /><br /><br /><br /><br />run_workqueue(cwq);<br /><br />}<br /><br /><br /><br /><br />return&nbsp;0;<br /><br />}<br /><br /><br /><br /><br />工作队列的应用:我在分析block的时候,就发现它使用了一个kblockd(static&nbsp;struct&nbsp;workqueue_struct&nbsp;*kblockd_workqueue;)的工作队列。<br /><br /><br />
armpc 发表于 2009-6-4 17:42 | 显示全部楼层

支持一下

  
miclinux 发表于 2009-6-24 13:20 | 显示全部楼层

好帖,跟

  
qtopia 发表于 2009-7-2 13:01 | 显示全部楼层

太乱了

  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

37

主题

53

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部