linux中断处理子系统小结
发表时间:2020-10-19
发布人:葵宇科技
浏览次数:66
前面的博文中, 大年夜致分散介绍了一些中断相干的器械, 然则对软中断的部分没有细心介绍, 在这里同一总结一下.
中断上半部的处理,汇编到request_irq的handle之间的过程.
http://blog.csdn.net/jackjones_008/article/details/42387241
MIPS平台的一点记录
http://blog.csdn.net/jackjones_008/article/details/41945909
tasklet/workqueue的介绍鄙人面这篇博文中有比较具体的介绍.
http://blog.csdn.net/jackjones_008/article/details/42295411
中断的处理, 起首当然是硬件中断产生后汇编部分的处理, 然后在hardirq处理完之后, 在函数irq_exit中, 如不雅发明当前没有hardirq并且softirq没有被禁止,
也没有pending的本地softirq, 则会显示的调用do_softirq 去处理softirq. 在处理softirq的过程中, 是会樊篱硬件中断的.
asmlinkage void do_softirq(void)
{
__u32 pending;
unsigned long flags;
if (in_interrupt())
return;
local_irq_save(flags);
pending = local_softirq_pending();
if (pending)
__do_softirq();
local_irq_restore(flags);
}在__do_softirq 琅绫擎, 在获得pending的softirq后, 又会打开硬件中断. 然后会去依次处理pending 的softirq.
这个依次, 其实就是根据enum中的定义大年夜 HI_SOFTIRQ 履行到 RCU_SOFTIRQ.
再多烦琐一下, 为什么会有pending的softirq呢, 因为代码有些处所去调用了 __raise_softirq_irqoff .
我们还可以留意到, __do_softirq 琅绫擎定义了一个max_restart, 这个值是10, 是体系的一个折中, 处理软中断, 然则不克不及过度的影响其他过程的履行.
完成不了的, 可以交给 ksoftirqd 这个内核thread去做.
asmlinkage void __do_softirq(void)
{
struct softirq_action *h;
__u32 pending;
int max_restart = MAX_SOFTIRQ_RESTART;
int cpu;
pending = local_softirq_pending();
account_system_vtime(current);
__local_bh_disable((unsigned long)__builtin_return_address(0));
trace_softirq_enter();
cpu = smp_processor_id();
restart:
/* Reset the pending bitmask before enabling irqs */
set_softirq_pending(0);
local_irq_enable();
h = softirq_vec;
do {
if (pending & 1) {
int prev_count = preempt_count();
h->action(h);
if (unlikely(prev_count != preempt_count())) {
printk(KERN_ERR "huh, entered softirq %td %p"
"with preempt_count %08x,"
" exited with %08x?\n", h - softirq_vec,
h->action, prev_count, preempt_count());
preempt_count() = prev_count;
}
rcu_bh_qsctr_inc(cpu);
}
h++;
pending >>= 1;
} while (pending);
local_irq_disable();
pending = local_softirq_pending();
if (pending && --max_restart)
goto restart;
if (pending)
wakeup_softirqd();
trace_softirq_exit();
account_system_vtime(current);
_local_bh_enable();
}enum
{
HI_SOFTIRQ=0,
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ,
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
NR_SOFTIRQS
};接上, restart 中处理完后, 还有pending的softirq的话, 就交给内核过程 ksoftirqd 去做. 这个内核过程也挥菰式的调用 do_softirq 去处理.
static int ksoftirqd(void * __bind_cpu)
{
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
preempt_disable();
if (!local_softirq_pending()) {
preempt_enable_no_resched();
schedule();
preempt_disable();
}
__set_current_state(TASK_RUNNING);
while (local_softirq_pending()) {
/* Preempt disable stops cpu going offline.
If already offline, we'll be on wrong CPU:
don't process */
if (cpu_is_offline((long)__bind_cpu))
goto wait_to_die;
do_softirq();
preempt_enable_no_resched();
cond_resched();
preempt_disable();
rcu_qsctr_inc((long)__bind_cpu);
}
preempt_enable();
set_current_state(TASK_INTERRUPTIBLE);
}
__set_current_state(TASK_RUNNING);
return 0;
wait_to_die:
preempt_enable();
/* Wait for kthread_stop */
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
schedule();
set_current_state(TASK_INTERRUPTIBLE);
}
__set_current_state(TASK_RUNNING);
return 0;
}
这时, 又弗成避免的回到了中断上半部和下半部的话题, 上半部我们可以懂得为一向履行到 request_irq 中注册的那个 handle 为止. 而softirq 开端的处理都是属于下半部的处理.
鄙人半部的处理中, 根据睡眠与否可以应用tasklet和workqueue的机制.
其实tasklet也是属于softirq的一种, 并且弗成睡眠. workqueue的机制则是交给了内核thread去履行, 可以许可睡眠.








