中断处理

中断的概念:用于CPU与外设之间信息交互的机制。

为什么需要中断?

1、外设的处理速度一般慢于CPU;

2、CPU不能一直等待外部事件

所以设备必须有一种方法来通知CPU它的工作进度,这种方法就是中断。

 

中断的实现:

1、向内核注册中断;

2、实现中断处理函数。

 

中断注册:

request_irq用于实现中断的注册功能 :

int request_irq(unsigned int irq,  //中断号

void (*handler)(int, void *, struct pt_regs *),   //中断处理程序

unsigned long flags,   //中断处理标志,与中断管理有关的各种选项

const char *devname,   //设备名

void *dev_id)          //共享中断时使用

返回0表示成功,或者返回一个错误码。

 

flags:

可以选择一些与中断管理有关的选项:

IRQF_DISABLE(SA_INTERRUPT)

如果设置该位,表示是一个“快速”中断处理程序;

快速:保证中断处理的原子性(不被打断)。“开启中断”标志位(处理器IF在运行快速中断处理程序时是关闭的,因此在服务该中断时,不会被其他类型的中断打断。不允许中断嵌套。

慢速:不保证中断处理的原子性。默认情况下,都是慢速中断。

IRQF_SHARED(SA_SHIRQ)

表明中断可以在设备间共享。

共享中断:将不同的设备挂到同一个中断信号线上。Linux对共享的支持主要是为PCI设备服务。

1、申请共享中断时,必须在flags参数中指定IRQF_SHARED位。

2、dev_id参数必须是唯一的。

why?在释放中断时候,会要求输入dev_id。如何做到唯一?

3、共享中断的处理程序中,不能使用disable_irq(unsigned int irq);

作用:关闭中断号irq所对应的中断。如果使用了这个函数,共享中断信号线的其它设备将同样无法使用中断,也就无法正常工作了。

IRQ_TYPE_EDGE_FALLING:下降沿中断

IRQ_TYPE_EDGE_RISING:上升沿中断

IRQ_TYPE_EDGE_BOTH: 两者都中断

 

释放中断:

当设备不再需要使用中断时(通常在驱动卸载时),应当把他们返还给系统:

void free_irq(unsigned int irq, void *dev_id);

 

中断处理程序:

中断处理程序就是普通的C代码。特别之处在于中断处理程序时在中断上下文中运行的,行为会受到某些限制:

1、不能向用户空间发送或接受数据

用户空间和进程对应,中断处理程序是属于中断上下文的,不对应任何进程。

2、不能使用可能引起阻塞的函数

阻塞函数是用于阻塞线程和进程的,所以不能使用

3、不能使用可能引起调度的函数

没有进程,无法调度

 

实现流程:

void short_sh_interrupt(int irq, void *dev_id, struct pt_regs *regs);

/*判断是否是本设备产生了中断(为什么要做这样的检测?)*/

/*因为共享中断的原因,内核收到中断以后,会去把中断线上的所有中断处理程序调用一遍,所以在处理的时候要做检查*/

value = inb(short_base); //short_base中断标志寄存器

if(!(value & 0x80)) return;

 

/*清除中断标志位(如果设备支持自动清除,则不需要这步)*/

outb(value & 0x7f, short_base);

 

/*中断处理,通常是数据接收等等。。*/

...

 

/*唤醒等待数据的进程(等待数据的时候发生的阻塞)*/

wake_up_interruptible(&short_queue);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值