linux平台下 延迟工作队列实例
? ? ? ? 工作隊(duì)列(work queue)是Linux內(nèi)核中將操作延期執(zhí)行的一種機(jī)制。因?yàn)樗鼈兪峭ㄟ^守護(hù)進(jìn)程在用戶上下文執(zhí)行,函數(shù)可以睡眠的時間,與內(nèi)核是無關(guān)的。在內(nèi)核版本2.5開發(fā)期間,設(shè)計(jì)了工作隊(duì)列,用以替換此前的keventd機(jī)制。
? ? ? ??這種機(jī)制和BH或Tasklets不同之處在于工作隊(duì)列是把延期的工作交由一個內(nèi)核線程去執(zhí)行,因此工作隊(duì)列的優(yōu)勢就在于它允許重新調(diào)度甚至睡眠。
? ? ? ??每個工作隊(duì)列多有一個數(shù)組,數(shù)據(jù)元素的數(shù)目與內(nèi)核處理器core的數(shù)目相同,每個數(shù)據(jù)元素都列出來將要延期執(zhí)行的任務(wù)。
? ? ? ??對于每個工作隊(duì)列來說,內(nèi)核都會創(chuàng)建一個新的內(nèi)核守護(hù)線程,延期任務(wù)使用上下文描述的等待隊(duì)列機(jī)制,在守護(hù)進(jìn)程的上下午執(zhí)行。
先定義幾個內(nèi)核中使用工作隊(duì)列時用到的術(shù)語方便后面描述。
- workqueues:所有工作項(xiàng)被 ( 需要被執(zhí)行的工作 ) 排列于該隊(duì)列,因此稱作工作隊(duì)列 (workqueues) 。
- worker thread:工作者線程 (worker thread) 是一個用于執(zhí)行工作隊(duì)列中各個工作項(xiàng)的內(nèi)核線程,當(dāng)工作隊(duì)列中沒有工作項(xiàng)時,該線程將變?yōu)?idle 狀態(tài)。
- single threaded(ST)::工作者線程的表現(xiàn)形式之一,在系統(tǒng)范圍內(nèi),只有一個工作者線程為工作隊(duì)列服務(wù)
- multi threaded(MT):工作者線程的表現(xiàn)形式之一,在多 CPU 系統(tǒng)上每個 CPU 上都有一個工作者線程為工作隊(duì)列服務(wù)
如何使用工作隊(duì)列哪?按如下步驟:
一.?????? 聲明一個工作隊(duì)列
staticstruct workqueue_struct *test_wq;
二.?????? 聲明一個延期工作描述實(shí)例
static struct delayed_work test_dwq;
三.?????? 聲明并實(shí)現(xiàn)一個工作隊(duì)列延遲處理函數(shù)
voiddelay_func(struct work_struct *work);
voiddelay_func(struct work_struct *work)
{
??? printk(KERN_INFO "My name isdelay_func!\n");
}
四.?????? 初始化一個工作隊(duì)列
test_wq = create_workqueue("test_wq");
五.?????? 任務(wù)初始化
INIT_DELAYED_WORK(&test_dwq,delay_func);
六. ? ? ? 向工作隊(duì)列提交工作項(xiàng)
queue_delayed_work(test_wq, &test_dwq, delay);
七. ? ? ? 取消工作隊(duì)列中的工作項(xiàng)
int cancel_delayed_work(test_wq);
? ? ? ?如果這個工作項(xiàng)在它開始執(zhí)行前被取消,返回值是非零。內(nèi)核保證給定工作項(xiàng)的執(zhí)行不會在調(diào)用 cancel_delay_work 成功后被執(zhí)行。 如果 cancel_delay_work 返回 0,則這個工作項(xiàng)可能已經(jīng)運(yùn)行在一個不同的處理器,并且仍然可能在調(diào)用 cancel_delayed_work 之后被執(zhí)行。要絕對確保工作函數(shù)沒有在 cancel_delayed_work 返回 0 后在任何地方運(yùn)行,你必須跟隨這個調(diào)用之后接著調(diào)用 flush_workqueue。在 flush_workqueue 返回后。任何在改調(diào)用之前提交的工作函數(shù)都不會在系統(tǒng)任何地方運(yùn)行。
八.?????? 刷新工作隊(duì)列
flush_workqueue(test_wq);
九.?????? 工作隊(duì)列銷毀
destroy_workqueue(test_wq);
?
涉及到的主要函數(shù)與結(jié)構(gòu)體
一.?????? 函數(shù)queue_delayed_work()
函數(shù)queue_delayed_work()是用于向工作隊(duì)列提交delayed_work實(shí)例,確保在延期執(zhí)行之前,至少會經(jīng)過由delay指定的一段時間(以jiffies為單位)。
該函數(shù)首先創(chuàng)建一個由內(nèi)核定時器,該定時器將在delayed jiffies之內(nèi)超時。
二.?????? 延期工作描述實(shí)例
structdelayed_work {
?????? struct work_struct work; /* 將作為實(shí)例被queue_work或queue_work_delayed添加到一個工作隊(duì)列*/
?????? struct timer_list timer; /* 延遲時間*/
};
三.?????? alloc_workqueue函數(shù)
struct workqueue_struct *alloc_workqueue(char *name, unsigned intflags, int max_active);
name:為工作隊(duì)列的名字,而不像 2.6.36 之前實(shí)際是為工作隊(duì)列服務(wù)的內(nèi)核線程的名字。
Flag: 指明工作隊(duì)列的屬性,可以設(shè)定的標(biāo)記如下:
- WQ_NON_REENTRANT:默認(rèn)情況下,工作隊(duì)列只是確保在同一 CPU 上不可重入,即工作項(xiàng)不能在同一 CPU 上被多個工作者線程并發(fā)執(zhí)行,但容許在多個 CPU 上并發(fā)執(zhí)行。但該標(biāo)志標(biāo)明在多個 CPU 上也是不可重入的,工作項(xiàng)將在一個不可重入工作隊(duì)列中排隊(duì),并確保至多在一個系統(tǒng)范圍內(nèi)的工作者線程被執(zhí)行。
- WQ_UNBOUND:工作項(xiàng)被放入一個由特定 gcwq 服務(wù)的未限定工作隊(duì)列,該客戶工作者線程沒有被限定到特定的 CPU,這樣,未限定工作者隊(duì)列就像簡單的執(zhí)行上下文一般,沒有并發(fā)管理。未限定的 gcwq 試圖盡可能快的執(zhí)行工作項(xiàng)。
- WQ_FREEZEABLE:可凍結(jié) wq 參與系統(tǒng)的暫停操作。該工作隊(duì)列的工作項(xiàng)將被暫停,除非被喚醒,否者沒有新的工作項(xiàng)被執(zhí)行。
- WQ_MEM_RECLAIM:所有的工作隊(duì)列可能在內(nèi)存回收路徑上被使用。使用該標(biāo)志則保證至少有一個執(zhí)行上下文而不管在任何內(nèi)存壓力之下。
- WQ_HIGHPRI:高優(yōu)先級的工作項(xiàng)將被排練在隊(duì)列頭上,并且執(zhí)行時不考慮并發(fā)級別;換句話說,只要資源可用,高優(yōu)先級的工作項(xiàng)將盡可能快的執(zhí)行。高優(yōu)先工作項(xiàng)之間依據(jù)提交的順序被執(zhí)行。
·?????????WQ_CPU_INTENSIVE:CPU 密集的工作項(xiàng)對并發(fā)級別并無貢獻(xiàn),換句話說,可運(yùn)行的 CPU密集型工作項(xiàng)將不阻止其它工作項(xiàng)。這對于限定得工作項(xiàng)非常有用,因?yàn)樗谕嗟?CPU 時鐘周期,所以將它們的執(zhí)行調(diào)度交給系統(tǒng)調(diào)度器。
·?????????WQ_DRAINING:internal: workqueue is draining
·?????????WQ_RESCUER :internal: workqueue has rescuer
·?????????WQ_MAX_ACTIVE: I like 512, better ideas?
·?????????WQ_MAX_UNBOUND_PER_CPU: 4 * #cpus for unbound wq
·?????????WQ_DFL_ACTIVE:等于WQ_MAX_ACTIVE / 2,
max_active:決定了一個 wq 在 per-CPU 上能執(zhí)行的最大工作項(xiàng)。比如 max_active 設(shè)置為 16 表示一個工作隊(duì)列上最多 16 個工作項(xiàng)能同時在 per-CPU 上同時執(zhí)行。當(dāng)前實(shí)行中,對所有限定工作隊(duì)列,max_active 的最大值是 512,而設(shè)定為 0 時表示是 256;而對于未限定工作隊(duì)列,該最大值為:MAX[512,4 * num_possible_cpus() ],除非有特別的理由需要限流或者其它原因,一般設(shè)定為 0 就可以了
實(shí)例
/*********************************************** Author: lewiyon@hotmail.com* File name: delay_wq.c* Description: learn delay workqueue* Date: 2011-12-21*********************************************/#include <linux/kernel.h> #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/workqueue.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/interrupt.h>static struct workqueue_struct *test_wq; static struct delayed_work test_dwq;void delay_func(struct work_struct *work);void delay_func(struct work_struct *work) {printk(KERN_INFO "My name is delay_func!\n"); }static int __init example_init(void) {test_wq = create_workqueue("test_wq");if (!test_wq) {printk(KERN_ERR "No memory for workqueue\n");return 1; }printk(KERN_INFO "Create Workqueue successful!\n");INIT_DELAYED_WORK(&test_dwq, delay_func);queue_delayed_work(test_wq, &test_dwq, 0);return 0; }static void __exit example_exit(void) {destroy_workqueue(test_wq);printk(KERN_INFO "Goodbay!\n"); }module_init(example_init); module_exit(example_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("lewiyon <lewiyon@hotmail.com>");轉(zhuǎn)載于:https://www.cnblogs.com/youngerchina/archive/2011/12/23/5624642.html
總結(jié)
以上是生活随笔為你收集整理的linux平台下 延迟工作队列实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Entity Framework中IQu
- 下一篇: 20个将 JavaScript 用到极致