工作的定义
if (!cwq->freezeable)
current->flags |= PF_NOFREEZE;
set_user_nice(current, -5);
在线程函数内设置了测试点如下
if (cwq->freezeable)
try_to_freeze();
如果设置了PF_NOFREEZE这个flag,那么系统挂起时候这个进程不会被挂起。
主要函数
#define create_workqueue(name) __create_workqueue((name), 0, 0) //多处理器时会为每个cpu创建一个工作者线程
#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1) //只创建一个工作者线程,系统挂起是线程也挂起
#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0) //只创建一个工作者线程,系统挂起是线程线程不挂起
以上三个宏调用__create_workqueue函数定义
extern struct workqueue_struct *__create_workqueue(const char *name,int singlethread, int freezeable);
释放创建的工作列队资源
void destroy_workqueue(struct workqueue_struct *wq)
延时调用指定工作列队的工作
queue_delayed_work(struct workqueue_struct *wq,struct delay_struct *work, unsigned long delay)
取消指定工作列队的延时工作
cancel_delayed_work(struct delay_struct *work)
将工作加入工作列队进行调度
queue_work(struct workqueue_struct *wq, struct work_struct *work)
等待列队中的任务全部执行完毕。
void flush_workqueue(struct workqueue_struct *wq);
主要测试代码
void myfunc(struct work_struct*ws);
struct workqueue_struct *wqueue;
DECLARE_WORK(mywork,myfunc);
void myfunc(struct work_struct*ws)
{
printk(KERN_ALERT "myfunc 1 current->pid %d\n",current->pid);
ssleep(1);
printk(KERN_ALERT "myfunc 2 current->pid %d\n",current->pid);
ssleep(1);
printk(KERN_ALERT "myfunc 3 current->pid %d\n",current->pid);
ssleep(1);
}
在模块加载是执行
wqueue=create_workqueue("myqueue");
queue_work(wqueue,&mywork);
printk(KERN_ALERT "main current->pid %d\n" ,current->pid);
测试结果
main current->pid 1010
myfunc 1 current->pid 1016
myfunc 2 current->pid 1016
myfunc 3 current->pid 1016
ps
....
1016 root 0 SW< [myqueue/0]
可见函数运行在pid为1016的进程中,ps查看进程名为myqueue/0.
实例说明:
1.使用自定义工作队列
//=========
#include>linux /kernel.h>
#include>linux/module.h>
#include>linux/proc_fs.h>
#include>linux/workqueue.h>
#include>linux/sched.h>
#include>linux/init.h>
#include>linux/interrupt.h>
#include>linux/delay.h>
struct workqueue_struct *test_wq;
struct delayed_work test_dwq;
void delay_func(struct work_struct *work);
void delay_func(struct work_struct *work)
{
int i;
printk(KERN_INFO "My name is delay_func!\n");
for (i = 0; i < 3; i++) {
printk(KERN_ERR "delay_fun:i=%d\n", i);
msleep(1000);
}
}
static int __init example_init(void)
{
int i;
int ret;
test_wq = create_workqueue("test_wq");
if (!test_wq) {
printk(KERN_ERR "No memory for workqueue\n");
return 1;
}
printk(KERN_INFO "Create Workqueue successful!\n");
INIT_DELAYED_WORK(&test_dwq, delay_func);
ret = queue_delayed_work(test_wq, &test_dwq, 5000);
printk(KERN_INFO "first ret=%d!\n", ret);
for (i = 0; i < 3; i++) {
printk(KERN_INFO "Example:ret= %d,i=%d\n", ret, i);
msleep(100);
}
ret = queue_delayed_work(test_wq, &test_dwq, 0);
printk(KERN_INFO "second ret=%d!\n", ret);
return 0;
}
static void __exit example_exit(void)
{
int ret;
ret = cancel_delayed_work(&test_dwq);
flush_workqueue(test_wq);
destroy_workqueue(test_wq);
printk(KERN_INFO "Goodbay! ret=%d\n", ret);
}
module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
运行结果:
kernel: Create Workqueue successful!
kernel: first ret=1!
kernel: Example:ret= 1,i=0
kernel: Example:ret= 1,i=1
kernel: Example:ret= 1,i=2
kernel: second ret=0!
kernel: Goodbay! ret=1
kernel: Create Workqueue successful!
说明将任务添加到工作队列后,如果工作队列还在执行该任务,则queue_delayed_work()返回1,否则返回0,如上实例所述;
主线程delay_wq将任务添加到工作队列后,使得工作队列在延迟delay后执行函数delay_func(),而delay_wq线程继续执行;
2.使用内核工作队列实例
#include>linux/module.h>
#include>linux/init.h>
#include>linux/kernel.h>
#include>linux/net.h>
#include>net/sock.h>
#include>linux/in.h>
#include>linux/types.h>
#include>linux/kthread.h>
#include>linux/wait.h>
#include>linux/skbuff.h>
#include>linux/string.h>
#include>asm-generic/unaligned.h>
#include>linux/sysctl.h>
#include>linux/netfilter.h>
#include>linux/netfilter_ipv4.h>
#include>asm/checksum.h>
#include>linux/ip.h>
#include>linux/workqueue.h>
#define err(msg) printk(KERN_INFO "%s failed.\n", msg)
static void defense_work_handler(struct work_struct *work);
static DECLARE_DELAYED_WORK(defense_work, defense_work_handler);
static void defense_work_handler(struct work_struct *work)
{
printk(KERN_INFO "defense_work_handler function.\n");
}
static int __init main_init(void)
{
schedule_delayed_work(&defense_work, 3 * HZ);
return 0;
}
static void __exit main_exit(void)
{
cancel_delayed_work_sync(&defense_work);
}
module_init(main_init);
module_exit(main_exit);
MODULE_LICENSE("GPL");
*********************************************************************************
以前内核里对这个函数是这样定义的 #define INIT_WORK(_work, _func, _data),可以理解为INIT_WORK会在你定义的_work工作队列里面增加一个工作任务,该任务就是_func。_func这个任务会需要一些数据作为参数,这个参数就是通过_data传递的。