简介
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_workqueue
workqueue_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");