工作佇列是一種不同於軟中斷和微執行緒的一種下半部延遲機制。工作佇列將工作延遲到乙個核心執行緒中執行,它執行在程序上下文中,它是可排程的,並且可以休眠。通常,如果延遲的工作中需要休眠,就使用工作佇列,否則使用軟中斷或微執行緒。由於核心開發者反對建立乙個新的核心執行緒,因此,應當盡量使用工作佇列,它其實是事先建立了乙個核心執行緒。
工作佇列的實現
工作佇列實際上是一種建立核心執行緒以處理從其他地方入隊的任務的介面。這些核心執行緒稱為工作者執行緒。你可以建立乙個特殊的工作者執行緒來處理延遲工作,然而,工作隊列為我們提供了乙個預設的工作者執行緒。在大多數情況下,直接使用該預設工作者執行緒就可以了。預設的工作者執行緒稱為events/n
,其中n
為處理器的編號。
代表執行緒的資料結構
struct workqueue_struct ;
每個處理器對應乙個struct cpu_workqueue_struct
的資料結構。
struct cpu_workqueue_struct ;
工作者執行緒的核心**如下:
for(;;)
在函式run_workqueue
(),執行實際的延遲工作:
while(!list_empty(&cwq->worklist))
工作佇列相關資料結構的關係
最上層的工作者執行緒,可能有多個型別。每個處理器上都有每一種型別的工作者執行緒。核心**可以根據需要建立工作者執行緒。預設情況下,工作者執行緒是events
。每個工作者執行緒由結構cpu_workqueue_struct
來表示。結構workqueue_struct
代表每個型別的所有工作者執行緒。例如,假設除了預設的events
型別的工作者執行緒外,還建立了乙個falcon
型別的工作者執行緒。假設計算機有4
個處理器,那麼有4
個events
執行緒(因而,有4
個cpu_workqueue_struct
結構)和4
個falcon
執行緒(因而,有另外4
個cpu_workqueue_struct
結構)。有2
個workqueue_struct
,分別對應events
型別和falcon
型別。使用預設的工作佇列
建立工作佇列
靜態方式:declare_work(name,void (*func)(void *), void *data);
動態方式:init_work(struct work_struct *work, void (*func)(void *), void *data);
工作佇列處理函式:void work_handler(void *data)
排程工作佇列:schedule_work(&work)
或schedule_delayed_work(&work,delay);
flush
工作佇列
void flush_scheduled_work(void);
該函式不能取消任何延遲的工作,即被schedule_delayed_work
()排程的工作。為了取消乙個延遲的工作,呼叫:int cancel_delayed_work(struct work_struct *work);
建立乙個新的工作佇列
struct workqueue_struct *create_workqueue(const char *name);
name
為工作佇列的名稱,如預設的工作佇列名稱為events
,如下所示:
struct workqueue_struct *keventd_wq;
keventd_wq= create_workqueue(「events」);
它將為每個處理器建立乙個工作者執行緒,並使之處於就緒狀態。
排程工作佇列
int queue_work(struct workqueue_struct *wq, struct work_struct *work)
int queue_delayed_work(struct workqueue_struct *wq, struct work_struct*work, unsigned long delay)
flush
乙個工作佇列
flush_workqueue(struct workqueue_struct *wq)
總結如下:
核心中提供了兩個輔助介面來使用工作佇列:
workqueue_struct
和work_struct
。使用步驟如下:
建立與乙個或多個核心執行緒關聯的工作佇列(
或乙個workqueue_struct
結構體)
。為了建立乙個服務於某個工作佇列的核心執行緒,使用create_singlethread_workqueue()
。建立系統中的乙個每-cpu
工作者執行緒,使用create_workqueue()
。核心也提供了預設的每-cpu
工作者執行緒供你直接使用(event/n
,其中n
是cpu號)。
建立乙個工作單元(
或乙個work_struct
變數)。乙個work_struct
變數使用init_work()
進行初始化。
提交工作單元到工作佇列中。使用queue_work()
將乙個工作單元提交到乙個專門的工作佇列中。使用schedule_work()
將乙個工作單元提交給預設的核心工作者執行緒。
工作佇列使用模板
usingworkqueue to offload work from interrupt handlers
struct roller_device_struct;
void __init roller_init()
/*the bottom half */
void
roller_analyze()
/*the interrupt handler */
static irqreturn_t
roller_interrupt(int irq, void *dev_id)
Linux下半部分機制 工作佇列
當我們編寫裝置中斷,必須要編寫中斷處理程式。中斷處理程式有些特點 1.關閉中斷情況下執行,這樣當負載很重時,影響系統效能。2.中斷處理程式中,不能進行睡眠。對於中斷處理程式限制,造就必須解決問題。解決方案把中斷處理分為兩部分上半部分和下半部分。上半部分就是執行中斷處理程式。下半部分就是突破上述限制。...
下半部機制之軟中斷
軟中斷 softirq 是用軟體方式模擬硬體中斷的概念,實現巨集觀上的非同步執行效果。softirq是基本的下半部機制,需要互斥使用。一般很少直接使用。通常只用在少數效能比較關鍵的子系統中。它是可重入的,允許乙個softirq的不同例項可同時執行在不同的處理器上。軟中斷的 位於kernel soft...
下半部機制之微執行緒
微執行緒 tasklet 是一種更通用的下半部機制,大多數情況下應該優先使用微執行緒,只有在對效能要求非常高的時候才考慮使用軟中斷。然而,微執行緒是基於軟中斷的,它實際上是乙個軟中斷。核心中的微執行緒用兩個軟中斷表示 hi softirq 和tasklet softirq 兩者唯一的區別在於hi s...