技術員聯(lián)盟提供win764位系統(tǒng)下載,win10,win7,xp,裝機純凈版,64位旗艦版,綠色軟件,免費軟件下載基地!

當前位置:主頁 > 教程 > 服務器類 >

linux中斷--中斷嵌套中斷請求丟失

來源:技術員聯(lián)盟┆發(fā)布時間:2018-08-18 12:16┆點擊:

  關于中斷嵌套:

  在linux內(nèi)核里,如果驅(qū)動在申請注冊中斷的時候沒有特別的指定,do_irq在做中斷響應的時候,是開啟中斷的,如果在驅(qū)動的中斷處理函數(shù)正在執(zhí)行的過程中,出現(xiàn)同一設備的中斷或者不同設備的中斷,這時候新的中斷會被立即處理,還是被pending,等當前中斷處理完成后,再做處理。

  在2.4和2.6內(nèi)核里,關于這一塊是否有什么不同。

  一般申請中斷的時候都允許開中斷,即不使用SA_INTERRUPT標志。如果允許共享則加上 SA_SHIRQ,如果可以為內(nèi)核熵池提供熵值(譬如你寫的驅(qū)動是ide之類的驅(qū)動),則再加上 SA_SAMPLE_RANDOM標志。這是普通的中斷請求過程。對于這種一般情況,只要發(fā)生中斷,就可以搶占內(nèi)核,即使內(nèi)核正在執(zhí)行其他中斷函數(shù)。這里有兩點說明:一是因為linux不支持 中斷優(yōu)先級,因此任何中斷都可以搶占其他中斷,但是同種類型的中斷(即定義使用同一個 中斷線的中斷)不會發(fā)生搶占,他們會在執(zhí)行本類型中斷的時候依次被調(diào)用執(zhí)行。二是所謂 “只要發(fā)生中斷,就可以搶占內(nèi)核”這句是有一定限制的,因為當中斷發(fā)生的時候系統(tǒng)由中斷門 進入時自動關中斷(對于x86平臺就是將eflags寄存器的if位置為0),只有當中斷函數(shù)被執(zhí)行 (handle_IRQ_event)的過程中開中斷之后才能有搶占。 對于同種類型的中斷,由于其使用同樣的idt表項,通過其狀態(tài)標志(IRQ_PENDING和 IRQ_INPROGRESS)可以防止同種類型的中斷函數(shù)執(zhí)行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函數(shù)被重入),對于不同的中斷,則可以自由的嵌套。因此,所謂中斷嵌套, 對于不同的中斷是可以自由嵌套的,而對于同種類型的中斷,是不可以嵌套執(zhí)行的。

  以下簡單解釋一下如何利用狀態(tài)標志來防止同種類型中斷的重入:

  當某種類型的中斷第一次發(fā)生時,首先其idt表項的狀態(tài)位上被賦予IRQ_PENDING標志,表示有待處理。 然后將中斷處理函數(shù)action置為null,然后由于其狀態(tài)沒有IRQ_INPROGRESS標志(第一次),故將其狀態(tài)置上IRQ_INPROGRESS并去處IRQ_PENDING標志,同時將action賦予相應的中斷處理函數(shù)指針(這里是一個重點,linux很巧妙的用法,隨后說明)。這樣,后面就可以順利執(zhí)行handle_IRQ_event進行中斷處理,當在handle_IRQ_event中開中斷后,如果有同種類型的中斷發(fā)生,則再次進入do_IRQ函數(shù),然后其狀態(tài)位上加上IRQ_PENDING標志,但是由于前一次中斷處理中加上的IRQ_INPROGRESS沒有被清除,因此這里無法清除IRQ_PENDING標志,因此action還是為null,這樣就無法再次執(zhí)行handle_IRQ_event函數(shù)。從而退出本次中斷處理,返回上一次的中斷處理函數(shù)中,即繼續(xù)執(zhí)行handle_IRQ_event函數(shù)。當handle_IRQ_event返回時檢查IRQ_PENDING標志,發(fā)現(xiàn)存在這個標志,說明handle_IRQ_event執(zhí)行過程中被中斷過,存在未處理的同類中斷,因此再次循環(huán)執(zhí)行handle_IRQ_event函數(shù)。直到不存在IRQ_PENDING標志為止。

  2.4和2.6的差別,就我來看,主要是在2.6中一進入do_IRQ,多了一個關閉內(nèi)核搶占的動作,同時在處理中多了一種對IRQ_PER_CPU類型的中斷的處理,其他沒有什么太大的改變。這類IRQ_PER_CPU的中斷主要用在smp環(huán)境下將中斷綁定在某一個指定的cpu上。例如arch/ppc/syslib/open_pic.c中的openpic_init中初始化ipi中斷的時候。

  其實簡單的說,中斷可以嵌套,但是同種類型的中斷是不可以嵌套的,因為在IRQ上發(fā)生中斷,在中斷響應的過程中,這個IRQ是屏蔽的,也就是這個IRQ的中斷是不能被發(fā)現(xiàn)的。

  同時在內(nèi)核的臨界區(qū)內(nèi),中斷是被禁止的

  關于do_IRQ可能會丟失中斷請求:

  do_IRQ函數(shù)是通過在執(zhí)行完handle_IRQ_event函數(shù)之后判斷status是否被設置了IRQ_PENDING標志來判斷是否還有沒有被處理的同一通道的中斷請求。 但是這種方法只能判斷是否有,而不能知道有多少個未處理的統(tǒng)一通道中斷請求。也就是說,假如在第一個中斷請求執(zhí)行handle_IRQ_event函數(shù)的過程中來了同一通道的兩個或更多中斷請求,而這些中斷不會再來,那么僅僅通過判斷status是否設置了IRQ_PENDING標志不知道到底有多少個未處理的中斷,handle_IRQ_event只會被再執(zhí)行一次。

  這算不算是個bug呢? 不算,只要知道有中斷沒有處理就OK了,知道1個和知道N個,本質(zhì)上都是一樣的。作為外設,應當能夠處理自己中斷未被處理的情況。

  不可能丟失的,在每一個中斷描述符的結構體內(nèi),都有一個鏈表,鏈表中存放著服務例程序

  關于中斷中使用的幾個重要概念和關系:

  一、基本概念

  1.

  產(chǎn)生的位置發(fā)生的時刻時序

  中斷CPU外部隨機異步

  異常CPU正在執(zhí)行的程序一條指令終止執(zhí)行后同步

  2.由中斷或異常執(zhí)行的代碼不是一個進程,而是一個內(nèi)核控制路徑,代表中斷發(fā)生時正在運行的進程的執(zhí)行

  中斷處理程序與正在運行的程序無關

  引起異常處理程序的進程正是異常處理程序運行時的當前進程

  二、特點

  1.(1)盡可能快

  (2)能以嵌套的方式執(zhí)行,但是同種類型的中斷不可以嵌套

  (3)盡可能地限制臨界區(qū),因為在臨界區(qū)中,中斷被禁止

  2.大部分異常發(fā)生在用戶態(tài),缺頁異常是唯一發(fā)生于內(nèi)核態(tài)能觸發(fā)的異常

  缺頁異常意味著進程切換,因此中斷處理程序從不執(zhí)行可以導致缺頁的操作

  3.中斷處理程序運行于內(nèi)核態(tài)

  中斷發(fā)生于用戶態(tài)時,要把進程的用戶空間堆棧切換到進程的系統(tǒng)空間堆棧,剛切換時,內(nèi)核堆棧是空的

  中斷發(fā)生于內(nèi)核態(tài)時, 不需要堆??臻g的切換

  三、分類

  1.中斷的分類:可屏蔽中斷、不可屏蔽中斷

  2.異常的分類:

  分類解決異常的方法舉例

  故障那條指令會被重新執(zhí)行缺頁異常處理程序

  陷阱會從下一條指令開始執(zhí)行調(diào)試程序

  異常中止強制受影響的進程終止發(fā)生了一個嚴重的錯誤

  四、IRQ

  1.硬件設備控制器通過IRQ線向CPU發(fā)出中斷,可以通過禁用某條IRQ線來屏蔽中斷。

  2.被禁止的中斷不會丟失,激活IRQ后,中斷還會被發(fā)到CPU

  3.激活/禁止IRQ線 != 可屏蔽中斷的 全局屏蔽/非屏蔽