简介
Linux中断的下半部分有四种处理方式。
- 工作队列
- Threaded IRQ
- Softirq
- Tasklet
linux中的工作队列
Work queues在linux 2.6版本加入的。工作队列是推迟工作的另一种形式。工作队列将工作推迟到内核线程中。下半部分始终在流程上下文中运行。因为工作队列允许用户创建内核线程并将工作绑定到内核线程。
在内核中有两种方式实现Workqueue。
- 使用全局的工作队列
- 创建自己的工作队列
全局工作队列的使用
工作队列的初始化
可以分为静态和动态两种方式。
# 静态DECLARE_WORK(workqueuename,workqueue_fn);# 动态
对应的API
int schedule_work( struct work_struct *work );int scheduled_delayed_work( struct delayed_work *dwork, unsigned long delay );int schedule_work_on( int cpu, struct work_struct *work );int scheduled_delayed_work_on(int cpu, struct delayed_work *dwork, unsigned long delay );# 删除队列int flush_work( struct work_struct *work );void flush_scheduled_work( void );# 取消工作int cancel_work_sync( struct work_struct *work );int cancel_delayed_work_sync( struct delayed_work *dwork );# 检查工作work_pending( work );delayed_work_pending( work );
代码
静态使用
#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/workqueue.h>// struct workqueue_struct *workqueue_test;// struct work_struct work_test;void work_test_func(struct work_struct *work) { printk("now this static workqueue has run\n"); }/*Creating work by Static Method */DECLARE_WORK(workqueue,work_test_func);static int test_init(void) {schedule_work(&workqueue);return 0;}static void test_exit(void) {printk("Goodbye,cruel world!\n");// destroy_workqueue(workqueue_test);}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");MODULE_DESCRIPTION("A simple workqueue driver");MODULE_VERSION("2:1.0");
动态使用
#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/workqueue.h>/* Work structure */static struct work_struct workqueue;void work_test_func(struct work_struct *work) { printk("now this Dynamic workqueue has run\n"); }static int test_init(void) {/*Creating work by Dynamic Method */INIT_WORK(&workqueue,work_test_func);schedule_work(&workqueue);return 0;}static void test_exit(void) {printk("Goodbye,cruel world!\n");}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");MODULE_DESCRIPTION("A simple workqueue driver");MODULE_VERSION("2:1.0");
创建自己的WorkQueue & 传递参数
#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/workqueue.h>struct workqueue_struct *workqueue_test;struct Mywork_struct{struct work_struct work_test;char *str;int Id;};struct Mywork_struct Mywork_struct[2];static char teststr[] = "test for demo work";void work_test_func(struct work_struct *work){struct Mywork_struct *PMyWork = container_of(work, struct Mywork_struct, work_test);printk("Id == %d,%s\n", PMyWork->Id, PMyWork->str);}static int test_init(void){int i = 0x00;printk("Hello,world!\n");/* 1. 自己创建一个workqueue, 中间参数为0,默认配置 *//* 或者也可以 create_workqueueworkqueue_test = create_workqueue("workqueue_test");*/workqueue_test = alloc_workqueue("workqueue_test", 0, 0);/*Creating workqueue */for (i = 0x0; i < sizeof(Mywork_struct) / sizeof(Mywork_struct[0]); i++){/* 2. 初始化工作项,并添加自己实现的函数 */INIT_WORK(&Mywork_struct[i].work_test, work_test_func);Mywork_struct[i].Id = i;Mywork_struct[i].str = teststr;}/* 3. 将自己的工作项添加到指定的工作队列去, 同时唤醒相应线程处理 */for (i = 0x0; i < sizeof(Mywork_struct) / sizeof(Mywork_struct[0]); i++){queue_work(workqueue_test, &Mywork_struct[i].work_test);}return 0;}static void test_exit(void){printk("Goodbye,cruel world!\n");destroy_workqueue(workqueue_test);}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");MODULE_DESCRIPTION("A simple workqueue driver");MODULE_VERSION("2:1.0");
