中断处理中tasklet与工作队列的使用

本文介绍了Linux内核中处理中断的方法,包括使用tasklet和工作队列进行下半部处理的基本原理及实现方式,并通过具体示例展示了如何申请和释放中断。

      在编写含有中断的程序中,少不了中断的申请(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");

 

只是简单的例子,说明使用方法而已,没有什么意义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值