标签:print 任务 基本 mic disable live 内核线程 entry post
一般对时间很敏感、和硬件相关、要保证不被其他中断(特别是同样的中断)打断的这些任务放在中断处理程序中运行。其他任务考虑放在下半部运行。
asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start___param[], __stop___param[]; smp_setup_processor_id(); ...... softirq_init();//初始化软中断 ...... /* Do the rest non-__init‘ed, we‘re now alive */ rest_init(); }
void __init softirq_init(void) { int cpu; for_each_possible_cpu(cpu) { int i; per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head; per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head; for (i = 0; i < NR_SOFTIRQS; i++) INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu)); } register_hotcpu_notifier(&remote_softirq_cpu_notifier); //此处注冊两个软中断 open_softirq(TASKLET_SOFTIRQ, tasklet_action); open_softirq(HI_SOFTIRQ, tasklet_hi_action); }
void open_softirq(int nr, void (*action)(struct softirq_action *)) { softirq_vec[nr].action = action; }
struct softirq_action { void (*action)(struct softirq_action *); }
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
从上面的代码中,我们能够看到:open_softirq()中.事实上就是对softirq_vec数组的nr项赋值.softirq_vec是一个32元素的数组,实际上linux内核仅仅使用了几项:
/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high frequency threaded job scheduling. For almost all the purposes tasklets are more than enough. F.e. all serial device BHs et al. should be converted to tasklets, not to softirqs. */ enum { HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, BLOCK_IOPOLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS };
有关网络子系统内容可參考文章:http://blog.csdn.net/shallnet/article/details/26269781
asmlinkage void do_softirq(void) { __u32 pending; unsigned long flags; //假设在硬件中断环境中就退出,软中断不能够在硬件中断上下文或者是在软中断环境中使用,使用in_interrupt()来防止软中断嵌套。和抢占硬中断环境。if (in_interrupt()) return; //禁止本地中断 local_irq_save(flags); pending = local_softirq_pending(); //假设有软中断要处理,则进入__do_softirq() if (pending) __do_softirq(); local_irq_restore(flags);
asmlinkage void __do_softirq(void) { struct softirq_action *h; __u32 pending; int max_restart = MAX_SOFTIRQ_RESTART; int cpu; pending = local_softirq_pending(); //pending用于保留待处理软中断32位位图 account_system_vtime(current); __local_bh_disable((unsigned long)__builtin_return_address(0)); lockdep_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) { //假设pending第n位被设置为1,那么处理第n位相应类型的软中断 int prev_count = preempt_count(); kstat_incr_softirqs_this_cpu(h - softirq_vec); trace_softirq_entry(h, softirq_vec); h->action(h); //运行软中断处理函数 trace_softirq_exit(h, softirq_vec); if (unlikely(prev_count != preempt_count())) { printk(KERN_ERR "huh, entered softirq %td %s %p" "with preempt_count %08x," " exited with %08x?\n", h - softirq_vec, softirq_to_name[h - softirq_vec], h->action, prev_count, preempt_count()); preempt_count() = prev_count; } rcu_bh_qs(cpu); } h++; pending >>= 1; //pending右移一位,循环检查其每一位 } while (pending); //直到pending变为0,pending最多32位,所以循环最多运行32次。 local_irq_disable(); pending = local_softirq_pending(); if (pending && --max_restart) goto restart; if (pending) wakeup_softirqd(); lockdep_softirq_exit(); account_system_vtime(current); _local_bh_enable(); }
标签:print 任务 基本 mic disable live 内核线程 entry post
原文地址:http://www.cnblogs.com/yfceshi/p/6984281.html