中断处理机制的实现

Linux中的中断处理系统非常依赖于体系结构,依赖于处理器、所使用的中断控制器(PIC--- programmable interrupt controller)、体系结构和机器本身。

1. 中断处理机制如下图所示:

设备产生中断,通过总线将电信号发送给中断控制器。如果中断号是激活的(中断号是允许被屏蔽的),那么中断控制器就会把中断发给处理器。
除非处理器上禁止了该中断号,否则处理器会立即停止它正在做的事,关闭中断系统,然后跳到内存中预定义的位置,开始执行那里的代码。
这个预定义的位置由内核设置,是中断处理程序的入口点。
对于每个中断号,处理器都跳到对应的一个(也是唯一)的位置。

 2. 这时, 内核会调用函数: do_IRQ():

处理IRQ: 不同平台,有不同的处理IRQ程序实现:
void do_IRQ(struct pt_regs *regs);
void do_IRQ(int irq, struct pt_regs *regs);
  pt_regs 是用于保存内核使用的寄存器的集合。各个平台的寄存器情况又各不相同。所以pt_regs 内容也不一样。

计算出中断号后,do_IRQ()会对所接收的中断进行应答,并禁止该中断号上的中断传递。

do_IRQ()需要确保在这条中断线上有一个有效的处理程序,这里do_IRQ()就调用了handle_IRQ_event(), 用来运行这个中断号上所安装的中断处理程序。

3. handle_IRQ_event(): 定义于<kernel/irq/handler.c>

/**
 * handle_IRQ_event - irq action chain handler
 * @irq:	the interrupt number
 * @action:	the interrupt action chain for this irq
 *
 * Handles the action chain of an irq event
 */
irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
{
	irqreturn_t ret, retval = IRQ_NONE;
	unsigned int status = 0;

	do {
		trace_irq_handler_entry(irq, action);
		ret = action->handler(irq, action->dev_id);
		trace_irq_handler_exit(irq, action, ret);

		switch (ret) {
		case IRQ_WAKE_THREAD:
			/*
			 * Set result to handled so the spurious check
			 * does not trigger.
			 */
			ret = IRQ_HANDLED;

			/*
			 * Catch drivers which return WAKE_THREAD but
			 * did not set up a thread function
			 */
			if (unlikely(!action->thread_fn)) {
				warn_no_thread(irq, action);
				break;
			}

			/*
			 * Wake up the handler thread for this
			 * action. In case the thread crashed and was
			 * killed we just pretend that we handled the
			 * interrupt. The hardirq handler above has
			 * disabled the device interrupt, so no irq
			 * storm is lurking.
			 */
			if (likely(!test_bit(IRQTF_DIED,
					     &action->thread_flags))) {
				set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
				wake_up_process(action->thread);
			}

			/* Fall through to add to randomness */
		case IRQ_HANDLED:
			status |= action->flags;
			break;

		default:
			break;
		}

		retval |= ret;
		action = action->next;
	} while (action);

	if (status & IRQF_SAMPLE_RANDOM)
		add_interrupt_randomness(irq);
	local_irq_disable();    //最后禁止中断, do_IRQ()期望中断一直是禁止的。

	return retval;
}
注意该函数参数:

一个是中断号,一个就是中断处理函数。

handle_IRQ_event()函数作用: 就是用来运行一个中断号对应的中断处理函数。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值