workqueue是另一種將工作推後的形式,它允許重新排程及休眠。
本文基於linux 核心4.10,workqueue 實現為cmwq(concurrency managed workqueue),引入cmwq的原因可以參考cmwq概述 。
workqueue資料結構
struct workqueue_struct ;
可以這樣理解,
work_struct: 工作
workqueue_struct:工作的集合
pool_workqueue: 中間人,負責建立起 workqueue 和 worker_pool 之間的關係。
worker_pool: 工人的集合
worker: 工人
1.workqueue的建立
#define alloc_ordered_workqueue(fmt, flags, args...) \
alloc_workqueue(fmt, wq_unbound | __wq_ordered | (flags), 1, ##args)
#define create_workqueue(name) \
alloc_workqueue("%s", __wq_legacy | wq_mem_reclaim, 1, (name))
#define create_freezable_workqueue(name) \
alloc_workqueue("%s", __wq_legacy | wq_freezable | wq_unbound | \
wq_mem_reclaim, 1, (name))
#define create_singlethread_workqueue(name) \
alloc_ordered_workqueue("%s", __wq_legacy | wq_mem_reclaim, name)
引數含義:
name: workqueue名字;
wq_non_reentrant:預設情況下,工作佇列只是確保在同一 cpu 上不可重入,即工作項不能在同一 cpu 上被多個工作者執行緒併發執行,但容許在多個 cpu 上併發執行。但該標誌標明在多個 cpu 上也是不可重入的,工作項將在乙個不可重入工作佇列中排隊,並確保至多在乙個系統範圍內的工作者執行緒被執行。
wq_unbound:沒有被限定到特定的 cpu,
wq_freezeable:可凍結 wq 參與系統的暫停操作。該工作佇列的工作項將被暫停,除非被喚醒,否則沒有新的工作項被執行。
wq_mem_reclaim:所有的工作佇列可能在記憶體**路徑上被使用。使用該標誌則保證至少有乙個執行上下文而不管在任何記憶體壓力之下。
wq_highpri:高優先順序的工作項將被排練在佇列頭上,並且執行時不考慮併發級別;換句話說,只要資源可用,高優先順序的工作項將盡可能快的執行。高優先工作項之間依據提交的順序被執行。
wq_cpu_intensive:cpu 密集的工作項對併發級別並無貢獻,換句話說,可執行的 cpu 密集型工作項將不阻止其它工作項。這對於限定得工作項非常有用,因為它期望更多的 cpu 時鐘週期,所以將它們的執行排程交給系統排程器。
第三個引數』1』: maxactive,決定了乙個wq在per-cpu上能執行的最大工作項。比如 max_active 設定為16,表示乙個工作佇列上最多16個工作項能同時在per-cpu上同時執行。
2.workqueue的初始化
#define init_work(_work, _func) \
__init_work((_work), (_func), 0)
#define init_work_onstack(_work, _func) \
__init_work((_work), (_func), 1)
#define init_delayed_work(_work, _func) \
__init_delayed_work(_work, _func, 0)
#define init_delayed_work_onstack(_work, _func) \
__init_delayed_work_onstack(_work, _func, 0)
#define init_deferrable_work(_work, _func) \
__init_delayed_work(_work, _func, timer_deferrable)
#define init_deferrable_work_onstack(_work, _func) \
__init_delayed_work_onstack(_work, _func, timer_deferrable)
3.workqueue的排程
extern
bool queue_work_on(int cpu, struct workqueue_struct *wq,
struct work_struct *work);
extern
bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *work, unsigned
long delay);
extern
bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned
long delay);
4.workqueue的銷毀
extern
void destroy_workqueue(struct workqueue_struct *wq);
#include
#include
#include
#include
#include
#include
#include
#include
void myfunc(struct work_struct*ws);
struct workqueue_struct *test_wq;
declare_work(mywork,myfunc);
void myfunc(struct work_struct *ws)
static
int __init test_init(void)
queue_work(test_wq, &mywork);
}static
void __exit test_exit(void)
module_init(test_init);
module_exit(test_exit);
module_license("gpl");
Linux中斷子系統
linux kernel的中斷子系統之 一 一 前言 乙個合格的linux驅動工程師需要對kernel中的中斷子系統有深刻的理解,只有這樣,在寫具體driver的時候才能 1 正確的使用linux kernel提供的的api,例如最著名的request threaded irq request ir...
linux中斷子系統
參考引用 wowotech 乙個很好的linux技術部落格。一 概述 目的kernel管理硬體裝置的方式 輪詢 中斷。中斷效率高且反應快於輪詢,因為它利用了硬體本身執行指令前會做的 中斷電訊號週期輪詢 分類中斷分為同步 synchronous 和非同步 asynchronous 同步也稱為異常,由c...
中斷子系統
linux kernel的中斷子系統之 一 綜述 linux kernel的中斷子系統之 二 irq domain介紹 linux kernel的中斷子系統之 三 irq number和中斷描述符 linux kernel的中斷子系統之 四 high level irq event handler ...