LKD Interrupts and Interrupt Handlers

Interrupts

硬件发送信号给进程产生中断,中断是异步产生的。中断由中断请求线(IRQ)来区分,IRQ是一个数值,一般来说0代表计时器,1代表键盘。
而异常一般是同步发生的,所以也叫做同步中断,当处理器执行指令时会产生异常:除0,页错误等等,当然还有前面讲过的系统调用。

Interrupt Handlers

中断处理函数也叫做中断服务程序,每个设备产生的中断都有一个相关的中断处理函数,中断处理函数是设备驱动的一部分。
中断处理函数运行的中断上下文中,在中断上下文中不会发生阻塞,不会发生进程调度,只可能被更高优先级的中断给中断。

Top Halves Versus Bottom Halves

中断分为两个部分,一个是top halves一个是bottom halves
中断服务程序就是top halves,关于buttom halvs以及为什么要分成两个部分下一章再讲。

Registering and Interrupt Handler

设备要使用中断必须先注册中断服务程序
/* request_irq: allocate a given interrupt line */

int request_irq(unsigned int irq,
		irq_handler_t handler,
		unsigned long flags,
		const char *name,
		voi *dev)

typedef irqreturn_t (*irq_handler_t)(int, void *);

其实就是一个申请中断请求线的过程。我们一个个来看这几个参数。

handler是一个中断处理函数句柄(一个指针指向中断处理函数)

标记位flags为有以下几种情况:
1.IRQF_DISABLED  关闭所有中断
2.IRQF_SAMPLE_RANDOM 看不懂= =。
3.IRQF_TIMER 指明是系统计时器引起的中断。
4.IRQF_SHARED 中断请求线可以被不同的中断处理函数共享

name是设备名称

dev用于共享中断请求线,当请求的中断请求线是共享的时候,必须设置dev。

request_irq()函数是可阻塞的,因此不能在中断上下文中被调用,原因就是里面有个kmalloc()不知道是从哪里冒粗来的。

void free_irq(unsigned int irq, void *dev)

 该函数用于释放中断处理函数,注意参数dev,这就是为什么共享请求线时为什么要设置dev,否则无法区分释放的是同一个irq中的哪个函数。

Writing and Interrupt Handler

主要是一些中断处理函数需要注意的地方。例如中断处理函数是不可重入的,当中断处理函数运行时,相应的中断请求线会被屏蔽,任何处理器都不能使用。

还有一点,当系统收到中断时,它会调用每一个同一中断线共享的每个函数,中断处理函数需要立马判断是否中断是由其对应的设备产生的(通过设备的寄存器),如不是则立刻退出。

中断服务程序中一般使用spin_lock()自旋锁来实现资源互斥。详细后面章节会介绍。

Interrupt Context

中断处理程序运行在中断上下文中,在中断上下文中没有对应的进程,由于没有后备进程,因此中断上下文中不能睡眠(阻塞),不能执行schedule(),可阻塞的函数不能出现在中断处理程序中。中断上下文有它自己独立的中断栈。

Implementing Interrupt Handlers

硬件发送电信号-> 中断控制器 -> 处理器 -> 处理机中断内核 -> 内核调用do_IRQ() -> 判断是否存在相应的中断处理函数 -> 若存在则执行handle_IRQ_event() -> ret_from_intr()返回被中断的内核代码处。

Interrupt Control

1.Disabling and Enabling Interrupts

通过下面两个函数可以关闭和开启当前处理机的中断:
local_irq_diasble();
/* interrupts are disabled .. */
local_irq_enable();


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值