在编写含有中断的程序中,少不了中断的申请(request_irq)及中断释放(free_irq),当然少不了对中断的处理,常用的中断处理方法有tasklet,工作队列以及软中断,其中tasklet和工作队列的使用法方类似,定义一个结构和一个处理函数,然后将结构与处理函数联系起来就可以了,下面通过2个例子说明:
tasklet的使用:
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
#include<linux/interrupt.h>
static int irq; //中断号
static char *devname; //设备名
static struct tasklet_struct mytasklet; //tasklet结构体
module_param(irq,int,0644);
module_param(devname,charp,0644);
struct myirq
{
int devid;
};
struct myirq mydev={1119};
static void mytasklet_handler(unsigned long data) //tasklet处理函数
{
printk("tasklet is working\n");
}
static irqreturn_t myirq_handler(int irq,void *dev) //中断处理函数
{
struct myirq mydev;
static int count =0 ;
mydev=*(struct myirq*)dev;
printk("key:%d\n",count+1);
printk("devid %d isr is working\n",mydev.devid);
printk("botoom half will be working\n");
tasklet_init(&mytasklet,mytasklet_handler,0); //初始化tasklet将tasklet结构与tasklet处理函数建立联系
tasklet_schedule(&mytasklet); //调用tasklet
printk("isr is leaving\n");
count++;
return IRQ_HANDLED;
}
static int __init myirq_init()
{
printk(KERN_NOTICE "MODULE is working...\n");
if(request_irq(irq,myirq_handler,IRQF_SHARED,devname,&mydev)!=0) //申请中断
{
printk("%s request irq %d faild\n",devname,irq);
return -1;
}
printk("%s request irq %d success \n",devname,irq);
return 0;
}
static int __exit myirq_exit()
{
printk("module is leaving\n");
free_irq(irq,&mydev); //释放中断
return 0;
}
module_init(myirq_init);
module_exit(myirq_exit);
MODULE_LICENSE("GPL");
工作队列使用:
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
#include<linux/interrupt.h>
#include<linux/workqueue.h>
static int irq;
static char *devname;
static struct work_struct mywork;
module_param(irq,int,0644);
module_param(devname,charp,0644);
struct myirq
{
int devid;
};
struct myirq mydev={1119};
static void mywork_handler(void *data)
{
printk("work is working\n");
}
static irqreturn_t myirq_handler(int irq,void *dev)
{
struct myirq mydev;
static int count =0 ;
mydev=*(struct myirq*)dev;
printk("key:%d\n",count+1);
printk("devid %d isr is working\n",mydev.devid);
printk("botoom half will be working\n");
INIT_WORK(&mywork,mywork_handler);
schedule_work(&mywork);
printk("isr is leaving\n");
count++;
return IRQ_HANDLED;
}
static int __init myirq_init()
{
printk(KERN_NOTICE "MODULE is working...\n");
if(request_irq(irq,myirq_handler,IRQF_SHARED,devname,&mydev)!=0)
{
printk("%s request irq %d faild\n",devname,irq);
return -1;
}
printk("%s request irq %d success \n",devname,irq);
return 0;
}
static int __exit myirq_exit()
{
printk("module is leaving\n");
free_irq(irq,&mydev);
return 0;
}
module_init(myirq_init);
module_exit(myirq_exit);
MODULE_LICENSE("GPL");
只是简单的例子,说明使用方法而已,没有什么意义。