linux中断处理子系统小结 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 技术分享 >

linux中断处理子系统小结

发表时间:2020-10-19

发布人:葵宇科技

浏览次数:43


前面的博文中, 大年夜致分散介绍了一些中断相干的器械, 然则对软中断的部分没有细心介绍, 在这里同一总结一下.
中断上半部的处理,汇编到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去履行, 可以许可睡眠.

相关案例查看更多