Linux 内核工作队列之work_struct 学习总结
前言
編寫Linux驅(qū)動(dòng)的時(shí)候?qū)τ趙ork_struct的使用還是很普遍的,很早之前就在閱讀驅(qū)動(dòng)源碼的時(shí)候就看到了它的蹤影,根據(jù)其命名大概知道了它的具體作用,但是仍然不知所以,同時(shí),伴隨出現(xiàn)的還有delayed_work以及workqueue_struct,抱著知其然并知其所以然的態(tài)度,在這里歸納總結(jié)一下work_struct,以及如何在驅(qū)動(dòng)中使用,因?yàn)楣ぷ麝?duì)列相對(duì)來(lái)說(shuō)比較復(fù)雜,篇幅和能力有限,只能介紹相對(duì)重要的部分。
workqueue
內(nèi)核里一直運(yùn)行類似worker thread,它會(huì)對(duì)工作隊(duì)列中的work進(jìn)行處理,大致的工作流程原理可以參考下圖所示;
在這里的work則是work_struct變量,并且綁定一個(gè)執(zhí)行函數(shù)——typedef void (*work_func_t)(struct work_struct *work);。在worker thread中會(huì)對(duì)非空的工作隊(duì)列進(jìn)行工作隊(duì)列的出隊(duì)操作,并運(yùn)行work綁定的函數(shù)。
work_struct
work_struct的數(shù)據(jù)結(jié)構(gòu)如下,暫時(shí)我們還無(wú)法關(guān)注其原理,只關(guān)注如何去開(kāi)啟一個(gè)work
#include <linux/include/workqueue.h>typedef void (*work_func_t)(struct work_struct *work);struct work_struct {atomic_long_t data;struct list_head entry;work_func_t func; #ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map; #endif };通過(guò)數(shù)據(jù)結(jié)構(gòu)可以知道,每當(dāng)我們定義一個(gè)work_struct變量的時(shí)候,需要綁定一個(gè)work_func_t類型的函數(shù)指針。
| INIT_WORK(_work, _func) | 初始化一個(gè)work |
| INIT_WORK_ONSTACK(_work, _func) | 在棧上初始化一個(gè)work |
| flush_work(struct work_struct *work); | 銷毀一個(gè)work |
| schedule_work(struct work_struct *work) | 調(diào)度一個(gè)work開(kāi)始運(yùn)行 |
例程
下面寫了 一個(gè)demo,模塊初始化之后會(huì)每隔5秒調(diào)度work開(kāi)始運(yùn)行,最終demo_work_func會(huì)運(yùn)行規(guī)定的次數(shù),并打印傳遞的參數(shù)和進(jìn)程信息。
#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[] = "test for demo work";struct work_ctx{struct work_struct real_work;char *str;int arg; }work_ctx;struct work_ctx *demo_work;static void demo_work_func(struct work_struct *work){struct work_ctx *temp_work = container_of(work,struct work_ctx,real_work);printk(KERN_INFO "[work]=> PID: %d; NAME: %s\n", current->pid, current->comm);printk(KERN_INFO "[work]=> sleep 1 seconds\n");set_current_state(TASK_INTERRUPTIBLE);schedule_timeout(1 * HZ); //Wait 1 secondsprintk(KERN_INFO "[work]=> data is: %d %s\n", temp_work->arg,temp_work->str); }static int __init demo_thread_init(void){int count = 10;demo_work = kmalloc(sizeof(*demo_work),GFP_KERNEL); INIT_WORK(&demo_work->real_work, demo_work_func);demo_work->str = data;while(count--){msleep(5000);demo_work->arg = count;schedule_work(&demo_work->real_work);}return 0; }module_init(demo_thread_init);static void __exit demo_thread_exit(void){flush_work(&demo_work->real_work);kfree(demo_work); } module_exit(demo_thread_exit);MODULE_LICENSE("GPL");運(yùn)行結(jié)果
[ 8.500146] [work]=> PID: 37; NAME: kworker/0:1 [ 8.500216] [work]=> sleep 1 seconds [ 9.499783] [work]=> data is: 9 test for demo work [ 13.503165] [work]=> PID: 37; NAME: kworker/0:1 [ 13.503213] [work]=> sleep 1 seconds [ 14.503122] [work]=> data is: 8 test for demo work [ 18.506493] [work]=> PID: 37; NAME: kworker/0:1 [ 18.506534] [work]=> sleep 1 seconds [ 19.506460] [work]=> data is: 7 test for demo work [ 23.509833] [work]=> PID: 37; NAME: kworker/0:1 [ 23.509874] [work]=> sleep 1 seconds [ 24.510060] [work]=> data is: 6 test for demo work [ 28.513161] [work]=> PID: 37; NAME: kworker/0:1 [ 28.513206] [work]=> sleep 1 seconds [ 29.513121] [work]=> data is: 5 test for demo work [ 33.516502] [work]=> PID: 37; NAME: kworker/0:1 [ 33.516545] [work]=> sleep 1 seconds [ 34.516452] [work]=> data is: 4 test for demo work [ 38.519819] [work]=> PID: 37; NAME: kworker/0:1 [ 38.519860] [work]=> sleep 1 seconds [ 39.519782] [work]=> data is: 3 test for demo work [ 43.523151] [work]=> PID: 37; NAME: kworker/0:1 [ 43.523191] [work]=> sleep 1 seconds [ 44.523117] [work]=> data is: 2 test for demo work [ 48.526495] [work]=> PID: 37; NAME: kworker/0:1 [ 48.526542] [work]=> sleep 1 seconds [ 49.526444] [work]=> data is: 1 test for demo work [ 53.539699] [work]=> PID: 37; NAME: kworker/0:1 [ 53.539763] [work]=> sleep 1 seconds [ 54.542925] [work]=> data is: 0 test for demo work參考
https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s08.html
https://kukuruku.co/post/multitasking-in-the-linux-kernel-workqueues/
總結(jié)
以上是生活随笔為你收集整理的Linux 内核工作队列之work_struct 学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java中的IO整理
- 下一篇: ES6点点点运算符