linux 中断下半部 工作队列

工作队列是另外一种下半部执行方式,工作队列在进程上下文执行,工作队列将要推后的工作交给一个内核线程去执行,因为工作队列工作在进程上下文,因此工作队列允许睡眠或重新调度。

因此如果你要推后的工作可以睡眠那么就可以选择工作队列,否则的话就只能选择软中断或 tasklet。

在前面中断的基础上实现:

1.定义结构体变量:

struct work_struct work; 

2.在中断初始化之后,初始化 INIT_WORK:

 INIT_WORK( 要初始化的工作 ,  工作对应的处理函数 );

 eg:INIT_WORK(&dev->work, key_work);

3.在中断上半部执行schedule_work:

schedule_work(&dev->work(要调度的工作));

4.调用key_work回调函数,执行中断下半部

static void key_work(struct work_struct *work)
{
    //struct imx6uirq_dev *dev = (struct imx6uirq_dev*)data;
    struct imx6uirq_dev *dev = container_of(work, struct imx6uirq_dev, work);

    dev->timer.data = (unsigned long)dev; //定时器回调函数参数
    mod_timer(&dev->timer, jiffies + msecs_to_jiffies(20)); /* 20ms定时 */ 

}

container_of函数:

container_of的主要作用是:通过已知的一个数据结构成员指针ptr,数据结构类型type,以及这个成员指针在这个数据结构中的成员名member,来获取指向这个数据结构的指针type *。

通过container_of可以获得该成员对应的变量的首地址。

5.参考例子

工作队列使用示例

/* 定义工作(work) */
struct work_struct testwork;

/* work 处理函数 */
void testwork_func_t(struct work_struct *work);
{
	/* work 具体处理内容 */
}

/* 中断处理函数 */
irqreturn_t test_handler(int irq, void *dev_id)
{
	......
	/* 调度 work */
	schedule_work(&testwork);
	......
}

/* 驱动入口函数 */
static int __init xxxx_init(void)
{
	......
	/* 初始化 work */
	INIT_WORK(&testwork, testwork_func_t);
	
	/* 注册中断处理函数 */
	request_irq(xxx_irq, test_handler, 0, "xxx", &xxx_dev);
	......
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值