W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
另一個(gè)有關(guān)于定時(shí)問(wèn)題的內(nèi)核設(shè)施是 tasklet 機(jī)制. 它大部分用在中斷管理(我們將在第 10 章再次見(jiàn)到).
tasklet 類似內(nèi)核定時(shí)器在某些方面. 它們一直在中斷時(shí)間運(yùn)行, 它們一直運(yùn)行在調(diào)度它們的同一個(gè) CPU 上, 并且它們接收一個(gè) unsigned long 參數(shù). 不象內(nèi)核定時(shí)器, 但是, 你無(wú)法請(qǐng)求在一個(gè)指定的時(shí)間執(zhí)行函數(shù). 通過(guò)調(diào)度一個(gè) tasklet, 你簡(jiǎn)單地請(qǐng)求它在以后的一個(gè)由內(nèi)核選擇的時(shí)間執(zhí)行. 這個(gè)行為對(duì)于中斷處理特別有用, 那里硬件中斷必須被盡快處理, 但是大部分的時(shí)間管理可以安全地延后到以后的時(shí)間. 實(shí)際上, 一個(gè) tasket, 就象一個(gè)內(nèi)核定時(shí)器, 在一個(gè)"軟中斷"的上下文中執(zhí)行(以原子模式), 在使能硬件中斷時(shí)執(zhí)行異步任務(wù)的一個(gè)內(nèi)核機(jī)制.
一個(gè) tasklet 存在為一個(gè)時(shí)間結(jié)構(gòu), 它必須在使用前被初始化. 初始化能夠通過(guò)調(diào)用一個(gè)特定函數(shù)或者通過(guò)使用某些宏定義聲明結(jié)構(gòu):
#include <linux/interrupt.h>
struct tasklet_struct {
/* ... */
void (*func)(unsigned long);
unsigned long data;
};
void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data);
DECLARE_TASKLET(name, func, data);
DECLARE_TASKLET_DISABLED(name, func, data);
tasklet 提供了許多有趣的特色:
一個(gè) tasklet 能夠被禁止并且之后被重新使能; 它不會(huì)執(zhí)行直到它被使能與被禁止相同的的次數(shù).
如同定時(shí)器, 一個(gè) tasklet 可以注冊(cè)它自己.
一個(gè) tasklet 能被調(diào)度來(lái)執(zhí)行以正常的優(yōu)先級(jí)或者高優(yōu)先級(jí). 后一組一直是首先執(zhí)行.
taslet 可能立刻運(yùn)行, 如果系統(tǒng)不在重載下, 但是從不會(huì)晚于下一個(gè)時(shí)鐘嘀噠.
一個(gè) tasklet 可能和其他 tasklet 并發(fā), 但是對(duì)它自己是嚴(yán)格地串行的 -- 同樣的 tasklet 從不同時(shí)運(yùn)行在超過(guò)一個(gè)處理器上. 同樣, 如已經(jīng)提到的, 一個(gè) tasklet 常常在調(diào)度它的同一個(gè) CPU 上運(yùn)行.
jit 模塊包括 2 個(gè)文件, /proc/jitasklet 和 /proc/jitasklethi, 它返回和在"內(nèi)核定時(shí)器"一節(jié)中介紹過(guò)的 /proc/jitimer 同樣的數(shù)據(jù). 當(dāng)你讀其中一個(gè)文件時(shí), 你取回一個(gè) header 和 sixdata 行. 第一個(gè)數(shù)據(jù)行描述了調(diào)用進(jìn)程的上下文, 并且其他的行描述了一個(gè) tasklet 過(guò)程連續(xù)運(yùn)行的上下文. 這是一個(gè)在編譯一個(gè)內(nèi)核時(shí)的運(yùn)行例子:
phon% cat /proc/jitasklet
time delta inirq pid cpu command
6076139 0 0 4370 0 cat
6076140 1 1 4368 0 cc1
6076141 1 1 4368 0 cc1
6076141 0 1 2 0 ksoftirqd/0
6076141 0 1 2 0 ksoftirqd/0
6076141 0 1 2 0 ksoftirqd/0
如同由上面數(shù)據(jù)所確定的, tasklet 在下一個(gè)時(shí)間嘀噠內(nèi)運(yùn)行只要 CPU 在忙于運(yùn)行一個(gè)進(jìn)程, 但是它立刻被運(yùn)行當(dāng) CPU 處于空閑. 內(nèi)核提供了一套 ksoftirqd 內(nèi)核線程, 每個(gè) CPU 一個(gè), 只是來(lái)運(yùn)行 "軟件中斷" 處理, 就像 tasklet_action 函數(shù). 因此, tasklet 的最后 3 個(gè)運(yùn)行在關(guān)聯(lián)到 CPU 0 的 ksoftirqd 內(nèi)核線程的上下文中發(fā)生. jitasklethi 的實(shí)現(xiàn)使用了一個(gè)高優(yōu)先級(jí) tasklet, 在馬上要來(lái)的函數(shù)列表中解釋.
jit 中實(shí)現(xiàn) /proc/jitasklet 和 /proc/jittasklethi 的實(shí)際代碼與 /proc/jitimer 的實(shí)現(xiàn)代碼幾乎是一致的, 但是它使用 tasklet 調(diào)用代替那些定時(shí)器. 下面的列表詳細(xì)展開(kāi)了 tasklet 結(jié)構(gòu)已被初始化后的內(nèi)核對(duì) tasklet 的接口:
void tasklet_disable(struct tasklet_struct *t);
這個(gè)函數(shù)禁止給定的 tasklet. tasklet 可能仍然被 tasklet_schedule 調(diào)度, 但是它的執(zhí)行被延后直到這個(gè) tasklet 被再次使能. 如果這個(gè) tasklet 當(dāng)前在運(yùn)行, 這個(gè)函數(shù)忙等待直到這個(gè)tasklet退出; 因此, 在調(diào)用 tasklet_disable 后, 你可以確保這個(gè) tasklet 在系統(tǒng)任何地方都不在運(yùn)行.
void tasklet_disable_nosync(struct tasklet_struct *t);
禁止這個(gè) tasklet, 但是沒(méi)有等待任何當(dāng)前運(yùn)行的函數(shù)退出. 當(dāng)它返回, 這個(gè) tasklt 被禁止并且不會(huì)在以后被調(diào)度直到重新使能, 但是它可能仍然運(yùn)行在另一個(gè) CPU 當(dāng)這個(gè)函數(shù)返回時(shí).
void tasklet_enable(struct tasklet_struct *t);
使能一個(gè)之前被禁止的 tasklet. 如果這個(gè) tasklet 已經(jīng)被調(diào)度, 它會(huì)很快運(yùn)行. 一個(gè)對(duì) tasklet_enable 的調(diào)用必須匹配每個(gè)對(duì) tasklet_disable 的調(diào)用, 因?yàn)閮?nèi)核跟蹤每個(gè) tasklet 的"禁止次數(shù)".
void tasklet_schedule(struct tasklet_struct *t);
調(diào)度 tasklet 執(zhí)行. 如果一個(gè) tasklet 被再次調(diào)度在它有機(jī)會(huì)運(yùn)行前, 它只運(yùn)行一次. 但是, 如果他在運(yùn)行中被調(diào)度, 它在完成后再次運(yùn)行; 這保證了在其他事件被處理當(dāng)中發(fā)生的事件收到應(yīng)有的注意. 這個(gè)做法也允許一個(gè) tasklet 重新調(diào)度它自己.
void tasklet_hi_schedule(struct tasklet_struct *t);
調(diào)度 tasklet 在更高優(yōu)先級(jí)執(zhí)行. 當(dāng)軟中斷處理運(yùn)行時(shí), 它處理高優(yōu)先級(jí) tasklet 在其他軟中斷之前, 包括"正常的" tasklet. 理想地, 只有具有低響應(yīng)周期要求( 例如填充音頻緩沖 )應(yīng)當(dāng)使用這個(gè)函數(shù), 為避免其他軟件中斷處理引入的附加周期. 實(shí)際上, /proc/jitasklethi 沒(méi)有顯示可見(jiàn)的與 /proc/jitasklet 的區(qū)別.
void tasklet_kill(struct tasklet_struct *t);
這個(gè)函數(shù)確保了這個(gè) tasklet 沒(méi)被再次調(diào)度來(lái)運(yùn)行; 它常常被調(diào)用當(dāng)一個(gè)設(shè)備正被關(guān)閉或者模塊卸載時(shí). 如果這個(gè) tasklet 被調(diào)度來(lái)運(yùn)行, 這個(gè)函數(shù)等待直到它已執(zhí)行. 如果這個(gè) tasklet 重新調(diào)度它自己, 你必須阻止在調(diào)用 tasklet_kill 前它重新調(diào)度它自己, 如同使用 del_timer_sync.
tasklet 在 kernel/softirq.c 中實(shí)現(xiàn). 2 個(gè) tasklet 鏈表( 正常和高優(yōu)先級(jí) )被聲明為每-CPU數(shù)據(jù)結(jié)構(gòu), 使用和內(nèi)核定時(shí)器相同的 CPU-親和 機(jī)制. 在 tasklet 管理中的數(shù)據(jù)結(jié)構(gòu)是簡(jiǎn)單的鏈表, 因?yàn)?tasklet 沒(méi)有內(nèi)核定時(shí)器的分類請(qǐng)求.
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: