用乙個工作佇列的例項來講解其使用

2021-08-29 02:17:09 字數 4032 閱讀 2698

1. source code

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct work_struct work_demo;

struct work_struct work_demo2;

struct workqueue_struct *workqueue_demo;

static void work_demo_func(struct work_struct *work)

static int workqueue_proc_show(struct seq_file *m, void *v)

static int workqueue_proc_open(struct inode *inode, struct file *file)

static ssize_t workqueue_proc_store(struct file *file, const char __user *buffer,

size_t count, loff_t *ppos)

else if(buf[0] == '2')

return count;

}static const struct file_operations workqueue_proc_fops = ;

static int __init workqueue_init(void)

static void __exit workqueue_exit(void)

module_init(workqueue_init);

module_exit(workqueue_exit);

module_license("gpl v2");

module_author("jon");

module_alias("platform");

module_description("workqueue demo driver");

2.測試過程

首先說明一下,如果呼叫的是「cat /proc/workqueue ",呼叫的是schedule_work,也就是使用系統的預設工作佇列。

隨後我們連續排程2次schedule_work看看會發生什麼

場景一:work_func中使用mdelay延遲10s,---- work_demo_func

/ # cat /proc/workqueue

workqueue_proc_show ,cpu id = 2

wake_up_worker

work_demo_func ,cpu id = 2,taskname = kworker/2:1

/ #/ #

/ # cat /proc/workqueue

workqueue_proc_show ,cpu id = 3

no wake_up_worker

…work_demo_func ,cpu id = 2,taskname = kworker/2:1

第一次排程後,由於work_func中排程的是mdelay,cpu 2在空轉,因此第二次排程工作佇列的時候執行的是cpu 3,但是由於同乙個work當前在cpu 2的normal執行緒池中執行,因此linux系統將本次排程的work依然分發給了cpu 2的執行緒池指向的worklist,等待上一次的work執行完成後再接著執行。

場景二:work_func中使用msleep延遲10s, ----work_demo_func

/ # cat /proc/workqueue

workqueue_proc_show ,cpu id = 3

wake_up_worker

work_demo_func ,cpu id = 3,taskname = kworker/3:1

/ #/ #

/ # cat /proc/workqueue

workqueue_proc_show ,cpu id = 3

wake_up_worker

/ #…

work_demo_func ,cpu id = 3,taskname = kworker/3:1

第一次排程的時候,由於work_func中執行的是msleep,因此cpu 3的當前程序進入阻塞,程序發生切換。第二次排程的時候由於上一次是msleep,因此本次執行的還是cpu 3只是程序的id不同罷了,由於當前執行緒池的所有執行緒全部都阻塞了,系統判定需要喚醒新的idle執行緒來執行這個work,隨後在work_thread的具體處理(process_one_work)中,系統發現本次work的上一次排程在該cpu的執行緒池中還沒有執行完畢,因此將其插入到scheduled的鍊錶後等待下次執行。

場景三:work_func中使用msleep,同時工作佇列採用自定義的percpu,max_active為2(意味著最多在每個cpu上併發2次)。同時採取2次排程不同的work

/ # echo 1 > /proc/workqueue

workqueue_proc_store ,work_demo,cpu id =0

wake_up_worker

queue work_demo end

work_demo_func ,cpu id =0,taskname = kworker/0:1

/ #/ # echo 2 > /proc/workqueue

workqueue_proc_store ,work_demo2,cpu id = 0

wake_up_worker

work_demo_func ,cpu id = 0,taskname = kworker/0:2

第一次排程的時候,核心是在cpu 0上排程的work_demo,由於work_func中執行的msleep,因此cpu 0在當前的程序中進入阻塞了,隨後程序傳送切換,第二次排程的時候由於上一次是msleep,因此本次執行的還是cpu 0只是程序的id不同罷了,由於當前執行緒池的所有執行緒全部阻塞了,系統判定需要喚醒新的idle執行緒來執行這個work,隨後在work_thread的具體處理(process_one_work)中,系統發現前後2次排程的是不同的work,滿足開新執行緒的條件,因此系統在當前cpu的執行緒池中開啟了乙個新的執行緒kworker/0:2來執行這個work。

場景四:work_func中使用mdelay,同時工作佇列採用自定義的percpu,max_active為2(意味著最多在每個cpu上併發2次)。同時採取2次排程不同的work

/ # echo 1 > /proc/workqueue

workqueue_proc_store ,work_demo,cpu id = 0

wake_up_worker

queue work_demo end

work_demo_func ,cpu id = 0,taskname = kworker/0:1

/ # echo 2 > /proc/workqueue

workqueue_proc_store ,work_demo2,cpu id = 2

wake_up_worker

work_demo_func ,cpu id = 2,taskname = kworker/2:1

第一次排程的時候,核心是在cpu 0上排程的work_demo,由於work_func中執行的mdelay,因此cpu 0在當前的程序中空轉,第二次排程的時候由於上一次是mdelay,因此本次執行的是cpu 2,由於當前執行緒池的所有執行緒全部阻塞了,系統判定需要喚醒新的idle執行緒來執行這個work,隨後在work_thread的具體處理(process_one_work)中,系統發現該work是第一次排程,滿足開新執行緒的條件,因此系統在當前cpu的執行緒池中開啟了乙個新的執行緒kworker/2:1來執行這個work。

用鍊錶寫的乙個佇列

以下是最近用鍊錶寫的乙個佇列,包括建立,入隊,出隊,列印等功能 filename linkqueue.c author haohaibo data 2017 4 12 brief 用鍊錶實現乙個佇列 include include include typedef int type t typedef...

用兩個棧模擬實現乙個佇列,其最大容量是多少?

題目 如何用兩個棧模擬實現乙個佇列?如果這兩個堆疊的容量分別是m和n m n 你的方法能保證佇列的最大容量是多少?這裡討論的是順序棧,如果是鏈式棧的話完全沒有必要考慮空間 分析 棧的特點是 後進先出 lifo 而佇列的特點是 先進先出 fifo 用兩個棧模擬實現乙個佇列的基本思路是 用乙個棧作為儲存...

乙個完整的php檔案上傳類例項講解

php define no file 不存在上傳檔案 define not allow ext 檔案型別不在允許範圍內 define not allow size 檔案大小不在允許範圍內 define has the file 該檔案已經存在 define upload failed 上傳失敗 de...