在linux核心中,對下半部(或者說推後執行的工作)的處理方式有好幾種,包括bh(bottom half),軟中斷,tasklets和工作佇列等等。在2.6核心中,大名鼎鼎的bh處理被廢除,新增了更方便的工作佇列。工作佇列的方便之處在於它把工作推後,交由乙個核心執行緒去執行,這個核心執行緒總會在程序上下文執行,因此,它就可以很方便的持有訊號量(semaphore),當然也可以允許睡眠。
核心對工作佇列的處理是通過工作者執行緒完成的。工作者執行緒在一般情況下處於睡眠狀態,當我們把需要推遲執行的工作註冊到工作佇列中之後,喚醒工作者執行緒會遍歷工作佇列中的每個待處理的工作,並執行工作佇列結構work_struct中的func函式。這裡涉及到兩個概念:工作者執行緒和工作佇列。首先看看我們最關心的工作佇列。
struct work_struct *delayed_work;
init_work(delayed_work, delayed_work_handler, data);
schedule_work(delayed_work);
delayed_work是我們宣告的工作佇列;通過init_work對工作佇列進行初始化,delayed_work_handler是工作佇列的處理函式,data是傳遞給處理函式的引數;最後呼叫schedule_work喚醒工作者執行緒處理推後執行的工作。如果需要經過一段延遲以後再執行工作,可以呼叫:
schedule_delayed_work(delayed_work, delay); //delay 是需要延遲的節拍數
另外還有一種靜態建立工作佇列的方式:
declare_work(name, void (*func) (void *), void *data);
大部分情況下我們了解到這裡已經足夠了。工作者執行緒可以放心的交給核心去完成。對於工作者執行緒的使用有兩種方式,一是直接使用核心中每個cpu對應的乙個預設工作者執行緒envents/n(n代表cpu的序號,從0開始);再者就是自己建立乙個專用的工作者執行緒。對於通常情況下,驅動開發者是不必關心工作者執行緒的,預設的工作者執行緒能夠做的很好。如果預設的佇列不能滿足要求,自己建立乙個工作者執行緒也很簡單,只需要呼叫:
struct workqueue_struct *create_workqueue(const char *name);
struct workqueue_struct *create_freezable_workqueue(const char *name);
struct workqueue_struct *create_singlethread_workqueue(const char *name);
this function creates a signal thread workqueue. which has one dedicated processes("kernel threads"), which runfunctions submitted to the queue.
排程時使用如下函式:
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);
它們與schedule_work()以及schedule_delayed_work()是類似的。
Linux 工作佇列
工作佇列 work queue 是另外一種將工作推後執行的形式,它和tasklet有所不同。工作佇列可以把工作推後,交由乙個核心執行緒去執行,也就是說,這個下半部分可以 在程序上下文中執行。這樣,通過工作佇列執行的 能佔盡程序上下文的所有優勢。最重要的就是工作佇列允許被重新排程甚至是睡眠。那麼,什麼...
linux工作佇列
linux工作佇列 1.功能描述 工作佇列 work queue 是linux kernel中將工作推後執行的一種機制。這種機制和bh或tasklets不同之處在於工作佇列是把推後的工作交由乙個核心執行緒去執行,因此工作佇列的優勢就在於它允許重新排程甚至睡眠。2.工作佇列結構體 typedef vo...
linux 工作佇列 補充
走入linux的殿堂已經有一年有餘了,在這裡我想將linux的各種實現機制分析一遍,一方面對自己來說也是溫故而知新,另一方面,促進大家的交流,最好能夠給大家一些拋磚引玉的啟迪。我是硬體出身,搞硬體已經好多年了,從是專門軟體開發也接近兩年了,在這一段時間內我越發認為軟硬體協同設計是未來發展的主流,軟硬...