[LDD3速记]_中断处理

一、安装中断处理

1. 申请中断

int request_irq(unsigned int irq,
                irqreturn_t (*handler)(int, void *, struct pt_regs *),
                unsigned long flags,
                const char *dev_name,
                void *dev_id);
/*
申请中断通道(成功返回0)
irq中断号;handler中断处理函数的指针;flag与中断管理有关的位掩码;
dev_id用于共享的中断信号线,可用于指向驱动程序自己的私有数据区,用来识别设备
*/

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

int can_request_irq(unsigned int irq, unsigned long flags);
/* 查询某个中断线是否可用,可用返回非零 */

        flags:

        SA_INTERRUPT:快速中断处理例程,运行于中断的禁用状态下(当前处理器上的其他所有中断都被禁止)

        SA_SHIRQ:中断可在设备间共享

        SA_SAMPLE_RANDOM:中断能对/dev/random设备和/dev/urandom设备使用的熵池(entropy pool)有贡献。熵池用来收集来自设备驱动程序和其它来源的环境噪音。add_interrupt_randomness()函数利用设备两次中断的间隔时间作为噪声源将随机数据加入熵池。


2. /proc接口

        /proc/interrupt:硬件中断产生时内部计数器递增,产生的报告显示在/proc/interrupt,只显示已安装了中断处理例程的中断,且在文件快照时没使用的话也不会出现。不依赖于体系结构。

        /proc/stat:记录了一些系统活动的底层统计信息(包括从系统启动开始接收到的中断数量)。所有中断线都会显示,字段的数量依赖于内核之下的硬件。


3. 自动检测IRQ号

        有些设备(如PCI标准)会声明打算使用的中断线,而另一些设备则需自动检测进行一些探测工作,决定使用哪条IRQ以便正确安装处理例程。

        装载时分配中断号:insmod xxx.ko irq=x

        内核辅助函数:

//1.分配中断的位掩码
unsigned long probe_irq_on(void);
/* 需保存返回的位掩码,且调用后需至少产生一次中断再调用下一个函数 */

//2.设备产生中断

//3.适当延时(留给中断探测)

//4.返回上述产生中断的编号
int probe_irq_off(unsigned long);
/* 若无中断发生则返回0,若产生了多次中断则返回负值 */

       DIY探测: 

       启用所有未被占用的中断,观察会发生什么(若不能预知可能的IRQ值,则需要探测0 - NR_IRQS-1所有中断)


二、中断处理例程

1. 限制

        不是在进程上下文运行,因此不能向空间发送或接收数据,不能休眠(wait_event、使用不带GFP_ATOMIC的内存分配操作、锁住一个信号量),不能调用schdule函数


2. 功能

        将有关中断接收的信息反馈给设备,根据中断不同含义对数据进行读写

        清除中断挂起位(有些设备没有,可在第一步也可在最后执行)

        通知进程事件已经发生(唤醒在该设备上休眠的进程)

static irqreturn_t sample_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
中断处理例程
irq:中断号
dev_id:区分共享中断线上的不同设备(中断处理程序)?
regs:可有可无?保存了处理器进入中断前的环境?
*/

        返回值:irqreturn_t:IRQ_HANDLED(确实需要处理);IRQ_NONE

        也可以用宏来产生返回值:IRQ_RETVAL(handled),如果需要处理该中断,则handled取非零,给内核使用以抑制假中断


3. 启用和禁用中断

void disable_irq(int irq);//禁用中断线,可嵌套调用,会等待正在执行的处理例程完成
void disable_irq_nosync(int irq);//立即返回,但可能会导致竞态
void enable_irq(int irq);//启用

void local_irq_save(unsigned long flags);
void local_irq_disable(void);
void local_irq_restore(unsigned long flags);
void local_irq_enable(void);
/* 禁用和启动所有中断 */

三、顶半部和底半部(上半部和下半部)

        顶半部:中断处理例程

        底半部:tasklet、工作队列


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值