LINUX软中断-ksoftirqd
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
前言
在上一篇 LINUX软中断-softirq的描述中提到过ksoftirqd这篇文章就介绍ksoftirqd
ksoftirqd 是什么
ksoftirqd 是个内核线程在创建的时候是绑定cpu的每一个core对应一个ksoftirqd 线程
比如当前系统有4个core
~# ps aux | grep ksoftirqd
root 3 0.0 0.0 0 0 ? S 14:20 0:00 [ksoftirqd/0] //core 0
root 9 0.0 0.0 0 0 ? S 14:20 0:00 [ksoftirqd/1] //core 1
root 12 0.0 0.0 0 0 ? S 14:20 0:00 [ksoftirqd/2] //core 2
root 15 0.0 0.0 0 0 ? S 14:20 0:00 [ksoftirqd/3] //core 3
ksoftirqd 的作用
ksoftirqd 的作用就是处理softirq用,它的本质就是调用 __do_softirq
ksoftirqd 的触发条件
- 通过中断
上一篇文章已经解释过了 softirq的处理流程是通过中断服务程序的第二个阶段即中断来了执行ISR后调用do_softirq遍历数组softirq_vec执行数组项的action但是个问题比如softirq_vec的第六项tasklet执行完又来了个ISR提交tasklet使得softirq_vec[6]有需要被处理这可如何是好呢
不能是卡在中断流程里吧这是就要唤醒本core上的ksoftirqd来处理softirq_vec数组看下代码
static int run_ksoftirqd(void * __bind_cpu)
{
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
preempt_disable();
if (!local_softirq_pending()) {
schedule_preempt_disabled();
}
__set_current_state(TASK_RUNNING);
while (local_softirq_pending()) {
if (local_softirq_pending())
__do_softirq();
}
}
return 0;
}
- tasklet_schedule
上篇文章讲过 通过调用 tasklet_schedule来提交 tasklettasklet_schedule除了可以再ISR中执行其实也可以在普通的线程中调用。
void __tasklet_schedule(struct tasklet_struct *t)
{
unsigned long flags;
local_irq_save(flags);
t->next = NULL;
*__this_cpu_read(tasklet_vec.tail) = t;
__this_cpu_write(tasklet_vec.tail, &(t->next));
raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_restore(flags);
}
//raise_softirq_irqoff
inline void raise_softirq_irqoff(unsigned int nr)
{
__raise_softirq_irqoff(nr);
/*
* If we're in an interrupt or softirq, we're done
* (this also catches softirq-disabled code). We will
* actually run the softirq once we return from
* the irq or softirq.
*
* Otherwise we wake up ksoftirqd to make sure we
* schedule the softirq soon.
*/
if (!in_interrupt())
wakeup_softirqd();
}
static void wakeup_softirqd(void)
{
/* Interrupts are disabled: no need to stop preemption */
struct task_struct *tsk = __this_cpu_read(ksoftirqd);
if (tsk && tsk->state != TASK_RUNNING)
wake_up_process(tsk);
}
由上面的代码得知__tasklet_schedule如果在中断上下文被调用的话则不唤醒ksoftirqd交给中断的下半段处理如果在普通线程被调用的话则唤醒ksoftirqd。注意唤醒的是本core上的ksoftirqd