linux 中断之工作队列workqueue (自己创建的工作队列,减小默认线程负担)

默认工作队列和自己创建工作队列对比介绍

1、上一节我们用的是schedule_work(&btn_work);  和 schedule_delayed_work(&btn_dwork, 5*HZ);调度任务

这两个调度函数都是把任务交个内核默认线程(event)管理执行,一旦向内核默认线程提交的任务太多,将导致内核默认线程负担太重,影响实时性

2、这一节我们使用的是queue_work(btn_wq, &btn_work); queue_delayed_work(btn_wq, &btn_dwork, 3*HZ);调度任务

这两个函数将会将我们的工作任务添加到自己的新创建的线程中,减小默认线程的负担

1、创建自己的工作队列

//分配工作队列的指针
static struct workqueue_struct *btn_wq;

//创建自己的工作队列和自己的内核线程
    btn_wq = create_workqueue("mybuttons");

2、登记调度

    //将自己的工作和自己的工作队列进行管理,然后再登记
    queue_work(btn_wq, &btn_work);

    //将自己延时的工作和自己的工作队列进行关联,然后再登记
    queue_delayed_work(btn_wq, &btn_dwork, 3*HZ);

参考代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>

//定义按键硬件相关的数据结构
struct button_resource {
    int irq;    //中断号
    char *name; //中断名称
};

//初始化按键信息
static struct button_resource btn_info[] = {
    [0] = {
        .irq = IRQ_EINT(0),
        .name = "KEY_UP"
    },
    [1] = {
        .irq = IRQ_EINT(1),
        .name = "KEY_DOWN"
    }
};

//分配工作和延时工作
static struct work_struct btn_work;
static struct delayed_work btn_dwork;

//分配工作队列的指针
static struct workqueue_struct *btn_wq;

//工作处理函数
static void btn_work_func(struct work_struct *work)
{
    printk("%s: %#x\n", __func__, work);
}

//延时工作处理函数
static void btn_dwork_func(struct work_struct *work)
{
    printk("%s: %#x\n", __func__, work);
}

//中断处理函数就是顶半部
static irqreturn_t button_isr(int irq, void *dev_id)
{
    //登记工作,内核会在适当的时候执行工作对应的处理函数
    //schedule_work(&btn_work);
    
    //登记延时工作,并且指定延时的时间间隔为3S
    //schedule_delayed_work(&btn_dwork, 3*HZ);

    //将自己的工作和自己的工作队列进行管理,然后再登记
    queue_work(btn_wq, &btn_work);

    //将自己延时的工作和自己的工作队列进行关联,然后再登记
    queue_delayed_work(btn_wq, &btn_dwork, 3*HZ);
    
    printk("%s\n", __func__);
    return IRQ_HANDLED; //处理完毕
}

static int btn_init(void)
{
    int i;

    printk("register irq!\n");

    for (i = 0; i < ARRAY_SIZE(btn_info); i++)
        request_irq(btn_info[i].irq, button_isr, 
                IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,
                btn_info[i].name, &btn_info[i]);
   
    //初始化工作和延时的工作
    INIT_WORK(&btn_work, btn_work_func); //指定工作处理函数
    INIT_DELAYED_WORK(&btn_dwork, btn_dwork_func); //指定延时工作处理函数
    printk("%s: %#x, %#x\n", 
            __func__, &btn_work, &btn_dwork);
    
    //创建自己的工作队列和自己的内核线程
    btn_wq = create_workqueue("mybuttons");
    return 0;
}

static void btn_exit(void)
{
    int i;

    printk("unregister irq!\n");

    //注意注册中断传递的参数和释放中断传递的参数一定要一致!
    for(i = 0; i < ARRAY_SIZE(btn_info); i++)
        free_irq(btn_info[i].irq, &btn_info[i]);
    
    //销毁自己的工作队列和内核线程
    destroy_workqueue(btn_wq);
}
module_init(btn_init);
module_exit(btn_exit);
MODULE_LICENSE("GPL");
发布了137 篇原创文章 · 获赞 106 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/shenlong1356/article/details/103296069