linux工作佇列 workqueue總覽

2021-08-20 15:07:45 字數 3570 閱讀 3018

1.linux工作佇列 - workqueue總覽

2.linux工作佇列 - workqueue_struct建立

3.linux工作佇列 - 把work_struct加入工作佇列

4.linux工作佇列 - work_struct被呼叫過程

有許多情況下需要非同步執行程序上下文,在linux中工作佇列(wq)是處理這種情況最常用的機制。在處理中斷中,對於中斷下半部的處理最常用的就是wq。

在原有的wq實現中,乙個多執行緒wq(mt wq)有乙個per cpu worker執行緒,乙個單執行緒wq有乙個系統範圍的worker執行緒。多執行緒wq(mt wq)的數量保持和cpu的個數一致,隨著近年來cpu core個數的增加,多執行緒wq(mt wq)的增加已經使得系統在32k pid的控制項接近飽和。

雖然mt wq消耗了大量資源,但是提供的併發執行水平還是得不到滿足。即使mt有很少的服務但是st wq和mt wq還是有限制。每個wq有自己單獨的worker pool,mtwq智慧型在per cpu執行,而stwq可以在整個系統執行。

cmwq(concurrency managed workqueue)是對原有wq的乙個重新實現,主要解決以下問題: 

a. api要能夠相容以前的wq實現 

b. 使用per-cpu的worker pool要能夠被所有的wq所共享,以便提供更好的併發靈活性,以免浪費資源 

c. 對於使用者要隱藏細節

工作佇列的整體設計框架如下圖,這裡有多個結構體,他們之間的關係下面說明

work_struct結構體代表的是乙個任務,它指向乙個待非同步執行的函式,不管驅動還是子系統什麼時候要執行這個函式,都必須把work加入到乙個workqueue。

worker結構體代表乙個工作者執行緒(worker thread),它主要乙個接乙個的執行掛入到佇列中的work,如果沒有work了,那麼工作者執行緒就掛起,這些工作者執行緒被worker-pool管理。

對於驅動和子系統的開發人員來說,接觸到的只有work,而背後的處理機制是管理worker-pool和處理掛入的work,這就是cmwq設計的不同。

worker-pool結構體用來管理worker,對於每一種worker pool都分兩種情況:一種是處理普通work,另一種是處理高優先順序的work。

workqueue_struct結構體代表的是工作佇列,工作佇列分unbound workqueue和bound workqueue。bound workqueue就是繫結到cpu上的,掛入到此佇列中的work只會在相對應的cpu上執行。unbound workqueue不繫結到特定的cpu,而且後台執行緒池的數量也是動態的,具體workqueue關聯到哪個worker pool,這是由workqueue_attrs決定的。

工作佇列從字面意義上很好理解,雖然背後的實現機制有點複雜,但是使用的時候還是簡單方便的,對於使用者來說,我們只要定義乙個work,然後把work加入到workqueue。如果當前沒有我們需要的workqueue,那麼我們需要自己建立乙個。

下文各個api的具體說明見include/linux/workqueue.h

//建立workqueue_struct

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

//銷毀workqueue_struct

extern

void destroy_workqueue(struct workqueue_struct *wq);

由上可以看出workqueue的建立根據flag的不同會建立不同種類的workqueue,但最終都會呼叫到介面alloc_workqueue,具體workqueue建立的過程及**分析見文章linux工作佇列 - workqueue_struct建立。

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

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

具體**分析見linux工作佇列 - 把work_struct加入工作佇列

Linux 工作佇列

工作佇列 work queue 是另外一種將工作推後執行的形式,它和tasklet有所不同。工作佇列可以把工作推後,交由乙個核心執行緒去執行,也就是說,這個下半部分可以 在程序上下文中執行。這樣,通過工作佇列執行的 能佔盡程序上下文的所有優勢。最重要的就是工作佇列允許被重新排程甚至是睡眠。那麼,什麼...

linux工作佇列

在linux核心中,對下半部 或者說推後執行的工作 的處理方式有好幾種,包括bh bottom half 軟中斷,tasklets和工作佇列等等。在2.6核心中,大名鼎鼎的bh處理被廢除,新增了更方便的工作佇列。工作佇列的方便之處在於它把工作推後,交由乙個核心執行緒去執行,這個核心執行緒總會在程序上...

linux工作佇列

linux工作佇列 1.功能描述 工作佇列 work queue 是linux kernel中將工作推後執行的一種機制。這種機制和bh或tasklets不同之處在於工作佇列是把推後的工作交由乙個核心執行緒去執行,因此工作佇列的優勢就在於它允許重新排程甚至睡眠。2.工作佇列結構體 typedef vo...