最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

工作隊列(work_queue)

2023-02-22 20:08 作者:秋名山西  | 我要投稿

工作隊列是linux 內(nèi)核中一種不同于軟中斷機(jī)制及其衍生類的最簡單、最常用的一種延遲機(jī)制。linux內(nèi)核提供的工作延遲機(jī)制有:

●SoftIrq:執(zhí)行在原子上下文

●Tasklet:執(zhí)行在原子上下文

●工作隊列:執(zhí)行在進(jìn)程上下文

可重入:如果代碼執(zhí)行期間隨處可以中斷,并且之后能夠被再次安全地調(diào)用,就稱為可再入

SoftIrq僅用于快速處理,直接使用的話需要考慮并發(fā)和可重入的問題,只有在網(wǎng)絡(luò)和塊設(shè)備子系統(tǒng)需要使用SoftIrq,其他情況下都可以使用Tasklet來代替SoftIrq。在絕大多數(shù)情況下,SoftIrq在硬件中斷中被調(diào)用,這些硬件中斷發(fā)生非??欤爝^對他們的服務(wù)速度,因此內(nèi)核有必要對他們進(jìn)行排隊,方便匹配對他們的服務(wù)速度。排隊的中斷會交給KsoftIrqd負(fù)責(zé)后期執(zhí)行,Ksoftirqd是單CPU內(nèi)核守護(hù)線程,用于處理未服務(wù)的軟件中斷。此外,SoftIrq是編譯時靜態(tài)分配的,不像Tasklet可以動態(tài)地進(jìn)行分配和刪除。

Tasklet是SoftIrq衍生的一種工作延遲機(jī)制,本質(zhì)是不可重入的。相同的tasklet只能被一個cpu(調(diào)度它的cpu)執(zhí)行,不同的Tasklet可以運(yùn)行在不同的cpu上。也就是說Tasklet只能被串行執(zhí)行,而SoftIrq可以被并發(fā)執(zhí)行,因此Tasklet性能不如SoftIrq,但是使用比較簡單。

工作隊列與前面兩種不同,他只能運(yùn)行在進(jìn)程上下文中,如果需要在中斷的下半部睡眠,工作隊列是惟一的選擇,這里的睡眠指的是處理I/O數(shù)據(jù)、持有互斥鎖延遲,以及可能導(dǎo)致睡眠或?qū)⑷蝿?wù)移除運(yùn)行隊列的所有其他任務(wù)。工作隊列又分為共享共享工作隊列和專用工作隊列。

工作隊列中把需要推后執(zhí)行的任務(wù)叫做work,使用work_struct來描述。

關(guān)于工作隊列的類型選擇?

除非別無選擇,或者需要關(guān)鍵性能,又或者需要控制從工作隊列初始化到每個工作隊列調(diào)度的細(xì)節(jié),如果只是偶爾提交任務(wù),就應(yīng)當(dāng)使用共享工作隊列。這種隊列為整個系統(tǒng)共享,可以獨占單不應(yīng)該長時間獨占該隊列。

由于工作隊列上掛起的任務(wù)在每個cpu上都是串行執(zhí)行的,因此不應(yīng)該任務(wù)不應(yīng)該長時間睡眠,因為它長時間睡眠會導(dǎo)致其他任務(wù)無法被調(diào)度運(yùn)行。共享工作隊列中的任務(wù)由每個cpu上內(nèi)核創(chuàng)建的event/n線程執(zhí)行。工作隊列機(jī)制不允許同一個工作多次加入到同一個隊列或者多個隊列中,只有當(dāng)work正在執(zhí)行或者已經(jīng)執(zhí)行完畢,才允許再次入隊。所以不存在多cpu并發(fā)執(zhí)行的問題。

共享隊列必須使用INIT_WORK宏進(jìn)行初始化

這個宏的作用是將自定義的數(shù)據(jù)結(jié)構(gòu)中的struct work_struct初始化為我們想要添加的任務(wù)func。

下面四個函數(shù)可以調(diào)度共享工作隊列上的工作,它們只是負(fù)責(zé)將work提交給cpu調(diào)度,什么時候執(zhí)行需要看cpu是否繁忙。

上面所說的四個函數(shù)都是將工作添加到系統(tǒng)共享隊列system_wq。已經(jīng)提交到共享隊列的工作可以通過函數(shù)cancel_delayed_work取消,然后再調(diào)用下面的函數(shù)刷新共享隊列,避免出現(xiàn)混亂。

void flush_schedule_work(void);

整個共享隊列被整個系統(tǒng)共享,因此在flush_shcedule_work返回前,不可能知道它會持續(xù)多久。

這里段代碼:

這里面涉及到了等待隊列和工作隊列,其中INIT_WORK宏將work與回調(diào)函數(shù)work_handler綁定,schdule_work負(fù)責(zé)將work加入到共享工作隊列,就是說當(dāng)work被cpu的event線程執(zhí)行時,執(zhí)行的就是函數(shù)work_handler。

而在這個程序中,還調(diào)用了wait_event_interruptible將模塊阻塞放進(jìn)等待隊列中,進(jìn)程在wait_event_interruptible調(diào)用出停止并睡眠。直到被放進(jìn)工作隊列的work對應(yīng)的回調(diào)函數(shù)被執(zhí)行(work_handler),修改阻塞任務(wù)的喚醒條件,然后喚醒任務(wù),將其狀態(tài)設(shè)置為TASK_RUNNING,放入工作隊列執(zhí)行。

專用工作隊列

這里,工作隊列使用struct workqueue_struct的實例代表,在工作隊列中排隊的工作使用struct work_struct 的實例進(jìn)行表示。在內(nèi)核線程中調(diào)度工作工作前需要執(zhí)行以下四步:

(1)聲明初始化 struct workqueue_struct

(2)創(chuàng)建工作函數(shù)(內(nèi)核線程執(zhí)行的回調(diào)函數(shù))

(3)創(chuàng)建struct work_struct,這樣就可以把工作函數(shù)嵌入到work_struct中。

(4)把工作函數(shù)嵌入work_struct中。

相關(guān)的數(shù)據(jù)結(jié)構(gòu)和函數(shù)定義在include/linux/workqueue.h中。

●聲明工作和工作隊列

struct workqueue_struct?*myqueue;

struct work_struct thework;

●定義工作函數(shù)(處理程序)

void dowork(void *data);

●初始化工作隊列,把工作嵌入到工作隊列中

myqueue = create_signlethread_workqueue("mywork");

INIT_WORK(&thework,dowork,<data-pointer>);

使用create_workqueue和create_signlethread_workqueue兩個函數(shù)都可以用來創(chuàng)建工作隊列,只不過前者創(chuàng)建的工作隊列會在每個可用的處理器上創(chuàng)建單獨的內(nèi)核線程。

●調(diào)度工作

queue_work(myqueue,&thework);

延遲指定時間后到指定工作現(xiàn)場排隊

queue_delayed_work(myqueue,&thework,<delay>);

如果工作已經(jīng)在隊列內(nèi),會返回false,否則會返回true。入隊前等待的jiffy數(shù),可以使用輔助函數(shù)msecs_to_jiffies把標(biāo)準(zhǔn)的ms延遲轉(zhuǎn)換為jiffy。例如要讓工作在5ms后入隊,則可以使用queue_delayed_work(myqueue,&thework,msecs_to_jiffies(5));

●等待指定隊列上所有的工作都執(zhí)行完畢

void flush_workqueue(struct worqueue_struct *wq);

通常使用這個函數(shù)關(guān)閉處理程序。

●清理

使用cancel_work_sync或者cancel_delayed_work_sync同步取消,他們將會取消還沒有運(yùn)行的工作,或者阻塞知道工作執(zhí)行完成,即使工作重新入隊,也會被取消。

linux v4.8以后的內(nèi)核,增加了異步取消的方法。cancel_work和cancel_delayed_work實現(xiàn)異步取消,必須檢查函數(shù)返回值是否為ture,確保工作自身沒有再次入隊。之后必須調(diào)用flush_workqueue顯式刷新隊列。

queue_work_on(int cpu,struct workqueue_struct *wq,struct work_struct work);

調(diào)度work,并指定運(yùn)行的cpu

總結(jié):在linux系統(tǒng)上,運(yùn)行任何中斷處理程序時,都會在所有處理器上禁用當(dāng)前對應(yīng)的中斷線,有時甚至需要在實際運(yùn)行中斷處理程序的cpu上禁止所有中斷。? 但絕不希望錯過任何中斷,所以引入了半部的概念,將中斷處理函數(shù)分為兩個部分。

首先上半部,他使用request_irq申請中斷資源,最終將根據(jù)需要屏蔽或者隱藏中斷,執(zhí)行快速操作,調(diào)度第二部分和下一部分,然后確認(rèn)中短線,所有被禁用的中斷都必須在退出下半部之前恢復(fù)啟用。

下半部會處理一些比較耗時的任務(wù),在他執(zhí)行期間,中斷會再次啟用,這樣就不會錯過中斷。下半部使用了工作延遲機(jī)制。SoftIrq\Tasklet\工作隊列\(zhòng)線程Irq。


工作隊列(work_queue)的評論 (共 條)

分享到微博請遵守國家法律
遂川县| 清原| 蒲城县| 兰溪市| 乐陵市| 威信县| 花莲县| 祁连县| 福泉市| 浮山县| 久治县| 日土县| 中江县| 舞钢市| 凤台县| 翁牛特旗| 墨竹工卡县| 伊宁县| 江安县| 无棣县| 阜宁县| 精河县| 博白县| 桓台县| 霍邱县| 军事| 澜沧| 广东省| 辽中县| 朝阳市| 滦南县| 阳曲县| 读书| 本溪| 健康| 吉木萨尔县| 吉林市| 东乡| 伊春市| 成都市| 南投县|