linux 内核 中断,工作队列 - Linux内核学习之中断_Linux教程_Linux公社-Linux系统门户网站...

[概述]

工作队列是一种将工作推后执行的的形式,工作队列可以把工作推后,交由一个内核线程去执行,占有进程上下文的所有优势,允许重新调度和睡眠。

[工作队列的实现]

工作队列子系统是一个用于创建内核线程的接口,通过它创建的进程负责执行由内核其他部分排到队列里的任务。它创建的这些内核线程称作工作者线程(worker thread)。工作队列子系统提供了一个缺省的工作者线程来处理推后的工作,所以我们大多数情况下,没必要自己去创建工作者线程,使用默认的就OK。

Linux kernel development 3 上对工作队列的实现原理讲的很清楚了,这里就不再详述。具体来看一个实例

[实例]

staticstructinput_dev *button_dev;

staticstructwork_struct button_wq;

在做实际的驱动开发的时候,不推荐使用全局变量,因为全局变量是造成竞争条件的主要原因。

[中断处理程序]

staticirqreturn_t button_interrupt(intirq,void*p)

{

schedule_work(&button_wq);

returnIRQ_RETVAL(IRQ_HANDLED);

}

schedule_work(&work)函数用来调度work,把work提交给缺省的events工作者线程(插入工作任务链表中)。work马上会被调度,一旦其所在的处理器上的工作者线程被唤醒,唤醒的工作者队列会遍历整个工作任务链表,如果有工作,它就会被执行,否则继续睡眠。

Schedule_work_delay(&work, delay) 和schedule_work函数的作用相同,唯一区别就是延迟delay时间后才会执行。

[工作队列处理函数]

voidwork_handler(void*data)

{

/*get pin value  */

intval = s3c2410_gpio_getpin(S3C2410_GPG(0));

input_report_key(button_dev,KEY_1, val);

input_sync(button_dev);

}

完成按键信息的获取和上报工作。

[模块初始化函数]

staticint__init button_init(void)

{

interr;

if(request_irq(BUTTON_IRQ, button_interrupt,

IRQ_TYPE_EDGE_BOTH,DEV_NAME, NULL)) {

printk(KERN_ERR"cannotallocate irq");

return- EBUSY;

}

……

INIT_WORK(&button_wq,work_handler);

printk("initialized\n");

return0;

}

初始化函数主要完成了两个工作:

1、  申请中断

2、  创建一个推后的工作button_wq,有两种方法:

动态创建:

INIT_WORK(struct work_struct work, void (*func)(void *)), 在新内核里,INIT_WORK已经发生了变化,少了第三个参数。可以参考http://www.linuxidc.com/Linux/2011-11/47658.htm

静态创建:

DECLARE_WORK(name,func) 创建一个名为name,处理函数为func的work_struct结构体。

不管是动态还是静态,都是填充work struct 结构体。

有兴趣可以去看内核里gpio_keys.c的实现代码,一个典型的work queue的实现例子。0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值