一,使用work_struct, INIT_WORK,queue_work, workqueue_struct,create_singlethread_workqueue (create_workqueue) 组合。
简单做一些解释:
workqueue_struct ---- queue 数据结构
queue_work ---- 启动的这个work。
create_workqueue ---- 用于创建一个workqueue队列,多核中,有个多个队列。为系统中的每个CPU都创建一个内核线程。
create_singlethread_workqueue ---- 用于创建一个workqueue队列,为多核中,也只创建一个内核线程。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/workqueue.h>
#include <linux/slab.h> //kmalloc kfree
#include <linux/sched.h>
#include <linux/delay.h>
static char data[] = "TTT queue work thread";
struct work_ctx{
struct work_struct A_work;
struct work_struct B_work;
char *str;
int arg;
}work_ctx;
static struct work_ctx *my_work;
static struct workqueue_struct* work_queue;
static void my_work_func_A(struct work_struct *work){
struct work_ctx *temp_work = container_of(work,struct work_ctx,A_work);
printk(KERN_INFO "[work]=> PID: A %d; NAME: %s\n", current->pid, current->comm);
printk(KERN_INFO "[work]=> sleep A 3 seconds\n");
// set_current_state(TASK_INTERRUPTIBLE);
msleep(3000); //Wait 3 seconds
printk(KERN_INFO "[work]=> data A is: %d %s\n", temp_work->arg, temp_work->str);
}
static void my_work_func_B(struct work_struct *work){
struct work_ctx *temp_work = container_of(work,struct work_ctx,B_work);
printk(KERN_INFO "[work]=> PID: B %d; NAME: %s\n", current->pid, current->comm);
printk(KERN_INFO "[work]=> sleep B 3 seconds\n");
// set_current_state(TASK_INTERRUPTIBLE);
msleep(3000); //Wait 3 seconds
printk(KERN_INFO "[work]=> data B is: %d %s\n", temp_work->arg, temp_work->str);
}
static int __init my_thread_init(void){
int count = 3;
work_queue = create_singlethread_workqueue("TTT_work_thread");
my_work = kmalloc(sizeof(*my_work),GFP_KERNEL);
if (work_queue != NULL) {
INIT_WORK(&my_work->A_work, my_work_func_A);
INIT_WORK(&my_work->B_work, my_work_func_B);
}
my_work->str = data;
while(count--){
msleep(5000);
my_work->arg = count;
if (work_queue != NULL) {
queue_work(work_queue, &my_work->A_work);
queue_work(work_queue, &my_work->B_work);
}
}
return 0;
}
module_init(my_thread_init);
static void __exit my_thread_exit(void){
flush_work(&my_work->A_work);
flush_work(&my_work->B_work);
destroy_workqueue(work_queue);
kfree(my_work);
}
module_exit(my_thread_exit);
MODULE_LICENSE("GPL");
运行结果:
[11432.420834] [work]=> PID: A 5530; NAME: kworker/u2:3
[11432.420835] [work]=> sleep A 3 seconds
[11435.492808] [work]=> data A is: 2 TTT queue work thread
[11435.492816] [work]=> PID: B 5530; NAME: kworker/u2:3
[11435.492817] [work]=> sleep B 3 seconds
[11438.564912] [work]=> data B is: 1 TTT queue work thread
[11438.564918] [work]=> PID: A 5530; NAME: kworker/u2:3
[11438.564919] [work]=> sleep A 3 seconds
[11441.636667] [work]=> data A is: 1 TTT queue work thread
[11441.636676] [work]=> PID: B 5530; NAME: kworker/u2:3
[11441.636677] [work]=> sleep B 3 seconds
[11444.709336] [work]=> data B is: 0 TTT queue work thread
[11444.709339] [work]=> PID: A 5530; NAME: kworker/u2:3
[11444.709339] [work]=> sleep A 3 seconds
[11447.780392] [work]=> data A is: 0 TTT queue work thread
[11447.780400] [work]=> PID: B 5530; NAME: kworker/u2:3
[11447.780400] [work]=> sleep B 3 seconds
[11450.852598] [work]=> data B is: 0 TTT queue work thread