日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 内核工作队列之work_struct 学习总结

發布時間:2023/12/16 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 内核工作队列之work_struct 学习总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

編寫Linux驅動的時候對于work_struct的使用還是很普遍的,很早之前就在閱讀驅動源碼的時候就看到了它的蹤影,根據其命名大概知道了它的具體作用,但是仍然不知所以,同時,伴隨出現的還有delayed_work以及workqueue_struct,抱著知其然并知其所以然的態度,在這里歸納總結一下work_struct,以及如何在驅動中使用,因為工作隊列相對來說比較復雜,篇幅和能力有限,只能介紹相對重要的部分。

workqueue

內核里一直運行類似worker thread,它會對工作隊列中的work進行處理,大致的工作流程原理可以參考下圖所示;

在這里的work則是work_struct變量,并且綁定一個執行函數——typedef void (*work_func_t)(struct work_struct *work);。在worker thread中會對非空的工作隊列進行工作隊列的出隊操作,并運行work綁定的函數。

work_struct

work_struct的數據結構如下,暫時我們還無法關注其原理,只關注如何去開啟一個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 };

通過數據結構可以知道,每當我們定義一個work_struct變量的時候,需要綁定一個work_func_t類型的函數指針。

函數功能
INIT_WORK(_work, _func)初始化一個work
INIT_WORK_ONSTACK(_work, _func)在棧上初始化一個work
flush_work(struct work_struct *work);銷毀一個work
schedule_work(struct work_struct *work)調度一個work開始運行

例程

下面寫了 一個demo,模塊初始化之后會每隔5秒調度work開始運行,最終demo_work_func會運行規定的次數,并打印傳遞的參數和進程信息。

#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");

運行結果

[ 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/

總結

以上是生活随笔為你收集整理的Linux 内核工作队列之work_struct 学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。