欢迎转载,转载时需保留作者信息,谢谢。
博客园地址:http://www.cnblogs.com/embedded-tzp
Csdn博客地址:http://blog.csdn.net/xiayulewa
早看到这篇文章,就不写了,懒:
Linux中断(interrupt)子系统之五:软件中断(softIRQ): http://blog.csdn.net/droidphone/article/details/7518428
1.1. 数据结构
struct softirq_action
{
void (*action)(struct softirq_action *);
};
2 static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
softirq_vec是一个struct softirq_action数组,使用open_softirq注册
Softirq.c (src\kernel):52 中:
2 irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;
其操作:raise_softirq_irqoff→or_softirq_pending置位bitmap:irq_stat[cpu].__softirq_pending
1.2. 软中断注册
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
softirq_vec[nr].action = action;
}
不是链表结构。
可被注册的有
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
};
如在softirq_init中有open_softirq(TASKLET_SOFTIRQ, tasklet_action);
这说明 tasklet是被放入软中断中执行的。
1.3. 软中断执行流程
1.3.1. 路径1:
open_softirq注册→raise_softirq→raise_softirq_irqoff→raise_softirq_irqoff→wakeup_softirqd
在wakeup_softirqd中唤醒ksoftirqd进程,
static struct smp_hotplug_thread softirq_threads = {
.store = &ksoftirqd,
.thread_should_run = ksoftirqd_should_run,
.thread_fn = run_ksoftirqd,
.thread_comm = "ksoftirqd/%u",
};
执行.thread_fn = run_ksoftirqd →__do_softirq
在 _do_softirq中有
h = softirq_vec;
……………………………
h->action(h); 即为具体注册函数
……………………………
Ksoftirqd:是个线程, 其流程为
start_kernel→rest_init→kernel_init→kernel_init_freeable
→do_basic_setup→do_initcalls→spawn_ksoftirqd
→smpboot_register_percpu_thread(&softirq_threads)
1.3.2. 路径2:
open_softirq注册→raise_softirq→raise_softirq_irqoff→raise_softirq_irqoff→irq_exit(在中断退出时执行)→invoke_softirq→do_softirq(或wakeup_softirqd) →__do_softirq→ h->action(h); 即为具体注册函数