網(wǎng)站例子友情鏈接作用
進(jìn)程上下文與中斷上下文
在Linux內(nèi)核中,“進(jìn)程上下文”和“中斷上下文”是兩種截然不同的執(zhí)行環(huán)境,理解它們的區(qū)別對(duì)于編寫(xiě)內(nèi)核代碼(尤其是驅(qū)動(dòng)程序)至關(guān)重要。核心區(qū)別在于它們與進(jìn)程(任務(wù))的關(guān)聯(lián)性以及內(nèi)核在該狀態(tài)下所能執(zhí)行的操作。
1. 進(jìn)程上下文 (Process Context)
- 定義:?當(dāng)內(nèi)核代表一個(gè)特定的用戶(hù)空間進(jìn)程(或內(nèi)核線(xiàn)程)執(zhí)行代碼時(shí)所處的環(huán)境。
- 關(guān)鍵特征:
- 關(guān)聯(lián)進(jìn)程:?總是與一個(gè)特定的?struct task_struct(進(jìn)程描述符)相關(guān)聯(lián)。內(nèi)核知道“當(dāng)前”正在為哪個(gè)進(jìn)程服務(wù)。
- 用戶(hù)空間映射:?當(dāng)前進(jìn)程的用戶(hù)空間內(nèi)存映射是有效的(通過(guò)進(jìn)程的頁(yè)表)。內(nèi)核可以(在需要時(shí))訪(fǎng)問(wèn)用戶(hù)空間內(nèi)存(例如,在系統(tǒng)調(diào)用期間復(fù)制數(shù)據(jù))。
- 可調(diào)度:?代碼運(yùn)行在進(jìn)程上下文中時(shí),是可以被搶占的。內(nèi)核可以在任何時(shí)候決定暫停當(dāng)前進(jìn)程的執(zhí)行,切換到另一個(gè)就緒進(jìn)程(進(jìn)程切換/上下文切換)。
- 可睡眠/阻塞:?在進(jìn)程上下文中執(zhí)行的代碼可以安全地調(diào)用可能引起睡眠或阻塞的函數(shù)(例如?kmalloc(GFP_KERNEL),?mutex_lock(),?wait_event(),?msleep())。當(dāng)發(fā)生睡眠時(shí):
- 內(nèi)核會(huì)保存當(dāng)前進(jìn)程的完整狀態(tài)(寄存器、堆棧指針、程序計(jì)數(shù)器等)。
- 調(diào)度器選擇一個(gè)新進(jìn)程運(yùn)行。
- 當(dāng)?shù)却氖录l(fā)生時(shí)(例如鎖可用、數(shù)據(jù)到達(dá)、超時(shí)),調(diào)度器最終會(huì)再次喚醒并恢復(fù)該進(jìn)程的執(zhí)行。
- 典型場(chǎng)景:
- 系統(tǒng)調(diào)用處理程序(如?read,?write,?open,?ioctl)。
- 內(nèi)核線(xiàn)程執(zhí)行的大部分代碼(除非顯式禁用搶占)。
- 代表進(jìn)程處理缺頁(yè)異常。
- 可延遲中斷處理(如軟中斷、tasklet、工作隊(duì)列)雖然由中斷觸發(fā),但通常被調(diào)度到進(jìn)程上下文中異步執(zhí)行。
- 類(lèi)比:?就像是你在專(zhuān)心做自己的工作(代表用戶(hù)進(jìn)程執(zhí)行內(nèi)核任務(wù)),但隨時(shí)可以被老板(調(diào)度器)打斷去處理其他事情,或者你自己覺(jué)得累了(需要等待資源)主動(dòng)去休息(睡眠),老板會(huì)安排別人工作,等你休息好了再回來(lái)繼續(xù)。
2. 中斷上下文 (Interrupt Context)
- 定義:?當(dāng)CPU響應(yīng)硬件中斷(IRQ)而執(zhí)行中斷處理程序時(shí)所處的環(huán)境。中斷的發(fā)生是異步的,與當(dāng)前運(yùn)行的進(jìn)程無(wú)關(guān)。
- 關(guān)鍵特征:
- 無(wú)關(guān)聯(lián)進(jìn)程:?與任何特定的進(jìn)程無(wú)關(guān)。?內(nèi)核不知道,也不關(guān)心當(dāng)前CPU上被打斷執(zhí)行的是哪個(gè)用戶(hù)進(jìn)程(或內(nèi)核線(xiàn)程)。current?宏指向的是被中斷的進(jìn)程,但中斷處理程序并不是在代表它執(zhí)行。
- 無(wú)用戶(hù)空間映射:?當(dāng)前被中斷進(jìn)程的用戶(hù)空間內(nèi)存映射通常無(wú)效。中斷處理程序不能直接訪(fǎng)問(wèn)用戶(hù)空間內(nèi)存(需要特殊機(jī)制)。
- 不可搶占:?中斷處理程序在默認(rèn)情況下運(yùn)行在關(guān)中斷(或至少關(guān)本地中斷)的狀態(tài)下。更高優(yōu)先級(jí)的中斷可以搶占它,但普通進(jìn)程調(diào)度在中斷上下文中是被禁止的。
- 嚴(yán)禁睡眠/阻塞:?這是最核心的限制!?在中斷上下文中執(zhí)行的代碼絕對(duì)不能調(diào)用任何可能導(dǎo)致睡眠或阻塞的函數(shù)(如分配內(nèi)存使用?GFP_KERNEL?標(biāo)志、獲取互斥鎖?mutex_lock()、主動(dòng)等待?wait_event()、延時(shí)?msleep()?等)。
- 快速執(zhí)行:?中斷處理程序的設(shè)計(jì)原則是盡可能快地處理中斷,確認(rèn)中斷源,執(zhí)行最必要的操作(如從硬件讀取數(shù)據(jù)到緩沖區(qū)),然后退出。將耗時(shí)任務(wù)推遲到進(jìn)程上下文(例如通過(guò)軟中斷、tasklet、工作隊(duì)列)是標(biāo)準(zhǔn)做法。
- 典型場(chǎng)景:
- 硬件中斷服務(wù)程序(ISR)的頂半部。
- 軟件中斷處理程序(softirq)的某些部分(雖然軟中斷本身在技術(shù)上可以看作一種特殊的中斷上下文,但其調(diào)度規(guī)則更復(fù)雜,但同樣嚴(yán)禁睡眠)。
- 類(lèi)比:?就像你正在專(zhuān)心工作(進(jìn)程上下文),突然電話(huà)鈴響了(硬件中斷)。你必須立刻接電話(huà)(進(jìn)入中斷上下文),處理電話(huà)內(nèi)容(中斷處理)。在這個(gè)過(guò)程中:
- 你不能離開(kāi)座位去休息(睡眠/阻塞)。
- 你不能直接處理需要離開(kāi)座位才能完成的事情(訪(fǎng)問(wèn)用戶(hù)空間)。
- 你接電話(huà)時(shí),老板(調(diào)度器)不能安排別人來(lái)替你做你原來(lái)的工作(進(jìn)程切換)。
- 你必須盡快處理完電話(huà),掛斷(退出中斷),然后才能繼續(xù)原來(lái)的工作或者讓老板安排別人工作。
為什么在中斷上下文中不能睡眠或切換進(jìn)程?
- 無(wú)進(jìn)程狀態(tài)可保存:?睡眠意味著進(jìn)程自愿放棄CPU。調(diào)度器需要保存當(dāng)前進(jìn)程的所有狀態(tài)(寄存器、堆棧、程序計(jì)數(shù)器等),以便稍后恢復(fù)。但中斷上下文不屬于任何進(jìn)程!內(nèi)核沒(méi)有與中斷處理程序本身關(guān)聯(lián)的?task_struct?結(jié)構(gòu)體來(lái)保存其狀態(tài)。內(nèi)核不知道“中斷處理程序進(jìn)程”應(yīng)該保存什么狀態(tài),也不知道恢復(fù)后從哪里開(kāi)始執(zhí)行。
- 調(diào)度器不可用:?進(jìn)程切換是由調(diào)度器完成的。調(diào)度器本身也是一個(gè)內(nèi)核函數(shù)。在中斷上下文中,特別是硬件中斷處理程序執(zhí)行期間,搶占通常是禁用的。嘗試調(diào)用調(diào)度器進(jìn)行進(jìn)程切換會(huì)導(dǎo)致未定義行為或嚴(yán)重錯(cuò)誤。
- 破壞被中斷進(jìn)程的狀態(tài):?中斷發(fā)生時(shí),被打斷的進(jìn)程(可能處于用戶(hù)態(tài)或內(nèi)核態(tài))的狀態(tài)被臨時(shí)保存在內(nèi)核棧上。如果中斷處理程序睡眠,調(diào)度器會(huì)切換到另一個(gè)進(jìn)程。當(dāng)原始中斷處理程序“理論上”被喚醒時(shí):
- 它恢復(fù)執(zhí)行的環(huán)境(棧、寄存器)可能已經(jīng)完全改變(被新進(jìn)程覆蓋)。
- 它試圖恢復(fù)的被中斷進(jìn)程的狀態(tài)可能已無(wú)效或丟失。
- 這必然導(dǎo)致系統(tǒng)崩潰或數(shù)據(jù)損壞。
- 死鎖風(fēng)險(xiǎn)極高:?假設(shè)中斷處理程序試圖獲取一個(gè)鎖(比如互斥鎖?mutex),而這個(gè)鎖恰好被中斷發(fā)生時(shí)正在運(yùn)行的那個(gè)進(jìn)程持有。如果中斷處理程序在獲取鎖時(shí)睡眠:
- 調(diào)度器切換到其他進(jìn)程運(yùn)行。
- 但持有鎖的那個(gè)進(jìn)程已經(jīng)被中斷打斷,它無(wú)法繼續(xù)執(zhí)行,也就無(wú)法釋放鎖!
- 中斷處理程序在等待鎖,而持有鎖的進(jìn)程在等待中斷處理完成才能繼續(xù)運(yùn)行(從而釋放鎖)。這就形成了經(jīng)典的死鎖。
- 違反實(shí)時(shí)性和性能要求:?中斷處理的目標(biāo)是快速響應(yīng)硬件事件。睡眠會(huì)導(dǎo)致中斷處理時(shí)間變得不可預(yù)測(cè)且非常長(zhǎng)(毫秒級(jí)甚至秒級(jí)),這會(huì)導(dǎo)致:
- 丟失后續(xù)的中斷(硬件緩沖區(qū)溢出)。
- 系統(tǒng)響應(yīng)遲滯。
- 破壞實(shí)時(shí)性保證。
總結(jié):
特性 | 進(jìn)程上下文 (Process Context) | 中斷上下文 (Interrupt Context) |
關(guān)聯(lián)進(jìn)程 | 是 (有?task_struct) | 否?(與任何進(jìn)程無(wú)關(guān)) |
用戶(hù)空間 | 有效 (可訪(fǎng)問(wèn)) | 無(wú)效?(通常不能直接訪(fǎng)問(wèn)) |
可搶占 | 是 (可被更高優(yōu)先級(jí)進(jìn)程/中斷搶占) | 受限 (可被更高優(yōu)先級(jí)中斷搶占,進(jìn)程調(diào)度禁止) |
可睡眠 | 是?(可調(diào)用阻塞函數(shù)) | 絕對(duì)禁止 |
可調(diào)度 | 是?(可被調(diào)度器切換出去) | 絕對(duì)禁止 |
執(zhí)行時(shí)長(zhǎng) | 相對(duì)較長(zhǎng) (允許執(zhí)行復(fù)雜任務(wù)) | 必須非常短?(盡快處理并退出) |
典型場(chǎng)景 | 系統(tǒng)調(diào)用、內(nèi)核線(xiàn)程、缺頁(yè)異常、工作隊(duì)列/tasklet | 硬件中斷處理程序 (頂半部)、部分 softirq |
current | 指向當(dāng)前運(yùn)行的進(jìn)程 | 指向被中斷的進(jìn)程 (不代表在執(zhí)行它) |
核心結(jié)論:?中斷上下文是一個(gè)與進(jìn)程無(wú)關(guān)、需要快速執(zhí)行的原子環(huán)境。它沒(méi)有進(jìn)程的“身份”和“狀態(tài)”供調(diào)度器管理,因此絕對(duì)不能睡眠或進(jìn)行進(jìn)程切換。任何可能引起睡眠的操作都必須推遲到進(jìn)程上下文(如工作隊(duì)列、內(nèi)核線(xiàn)程)中執(zhí)行。違反這條規(guī)則是內(nèi)核開(kāi)發(fā)中的嚴(yán)重錯(cuò)誤,幾乎必然導(dǎo)致系統(tǒng)崩潰或死鎖。
簡(jiǎn)言之,中斷處理程序和被中斷進(jìn)程之間,沒(méi)有什么瓜葛,不具有綁定關(guān)系或代表關(guān)系,決不能通過(guò)進(jìn)程調(diào)度恢復(fù)中斷的執(zhí)行。如果,非要在兩者之間找一點(diǎn)關(guān)系的話(huà),那就是中斷處理程序借用被中斷進(jìn)程的內(nèi)核棧(這一點(diǎn)也是可選地,linux允許設(shè)置獨(dú)立內(nèi)核棧)。