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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: linux