外部中斷
外部硬件的中斷是通過(guò)兩根信號(hào)線通知CPU的比被,這兩根信號(hào)線就是INTR(INTeRrupt)和NMI(Non Maskable Interrupt)
- NMI中斷,不可屏蔽中斷,產(chǎn)生這個(gè)中斷的時(shí)候,表示系統(tǒng)發(fā)生了致命的錯(cuò)誤。
- INTR可屏蔽中斷毫深。
中斷程序會(huì)分為上半部和下半部嵌纲,把中斷程序需要立即執(zhí)行的部分劃分到上半部分师溅,這部分是要限時(shí)執(zhí)行的棚贾。上半部實(shí)在關(guān)中斷不被打擾的情況下執(zhí)行的。當(dāng)上半部執(zhí)行完成后就把中斷打開(kāi)了崭篡;下半部也屬于中斷程序,其在開(kāi)中斷的情況下執(zhí)行,如果有新的中斷發(fā)生壮池,原來(lái)這個(gè)舊中斷的下半部就會(huì)被換下CPU,先執(zhí)行新的中斷程序的上半部创译,等待線程調(diào)度機(jī)制為舊中斷處理程序選擇一個(gè)日期(依靠調(diào)度算法)初茶,再調(diào)度CPU完成下半部的執(zhí)行猛铅。
內(nèi)部中斷
內(nèi)部中斷可以分為軟中斷和異常
-
int 8位立即數(shù)
可以通過(guò)它進(jìn)行系統(tǒng)調(diào)用富俄,可以表示256種中斷,這與處理器所支持的中斷數(shù)是相吻合的康辑。 -
int3
注意胖齐,int和3之間沒(méi)有空格,int3
是調(diào)試斷點(diǎn)命令讼稚,其所出發(fā)的中斷向量號(hào)為3 -
into
這是中斷溢出指令,他所出發(fā)的中斷向量號(hào)為4收津,但是肌割,能否引發(fā)4號(hào)中斷是要看eflags標(biāo)志寄存器的OF位是否為1,如果是1才會(huì)引發(fā)中斷挥萌,否則這個(gè)指令什么都不做。 -
bound
這是檢查數(shù)組索引越界指令措译,它可以觸發(fā)5號(hào)中斷是晨,用于檢查數(shù)組的索引下標(biāo)是否在上下邊界之內(nèi)桶至,該指令的格式是bound 16/32位寄存器 16/32位內(nèi)存
,目的操作數(shù)使用寄存器來(lái)存儲(chǔ)的,其內(nèi)容是待檢測(cè)的數(shù)組的下標(biāo)值佩伤。源操作數(shù)是內(nèi)存疯汁,其內(nèi)容是數(shù)組下標(biāo)的下邊界和上邊界犹赖。當(dāng)執(zhí)行bound
指令時(shí),如果下標(biāo)處于數(shù)組索引的范圍之外,則會(huì)觸發(fā)5號(hào)中斷俭缓。 -
ud2
未定義指令不从,這會(huì)觸發(fā)第6號(hào)中斷。表示指令無(wú)效,CPU無(wú)法識(shí)別扔役。常用于軟件測(cè)試中吟温,沒(méi)有實(shí)際用途榄檬。
中斷處理過(guò)程及保護(hù)
完整的中斷過(guò)程分為 CPU 外和 CPU 內(nèi)兩部分。
- CPU 外:外部設(shè)備的中斷由中斷代理芯片接收鹿榜,處理后將該中斷的中斷向量號(hào)發(fā)送到 CPU海雪。
- CPU 內(nèi): CPU 執(zhí)行該中斷向量號(hào)對(duì)應(yīng)的中斷處理程序。 CPU 外這部分的處理過(guò)程舱殿,在后面中斷代理芯片 Intel 8259A 時(shí)大家就會(huì)了解奥裸,這部分內(nèi)容 屬于硬件范疇,我們這里只討論處理器內(nèi)的過(guò)程沪袭,這是軟件能控制的部分湾宙。
- 處理器根據(jù)中斷向量號(hào)定位中斷門(mén)描述符。
中斷向量號(hào)是中斷描述符的索引冈绊,當(dāng)處理器收到一個(gè)外部中斷向量號(hào)后侠鳄,它用此向量號(hào)在中斷描述符 表中查詢對(duì)應(yīng)的中斷描述符,然后再去執(zhí)行該中斷描述符中的中斷處理程序死宣。由于中斷描述符是 8 個(gè)字節(jié)伟恶, 所以處理器用中斷向量號(hào)乘以 8 后,再與 IDTR 中的中斷描述符表地址相加毅该,所求的地址之和便是該中斷 向量號(hào)對(duì)應(yīng)的中斷描述符博秫。 - 處理器進(jìn)行特權(quán)級(jí)檢查。
由于中斷是通過(guò)中斷向量號(hào)通知到處理器的眶掌,中斷向量號(hào)只是個(gè)整數(shù)台盯,其中并沒(méi)有 RPL,所以在對(duì)由中斷引起的特權(quán)級(jí)轉(zhuǎn)移做特權(quán)級(jí)檢查中畏线,并不涉及到 RPL静盅。中斷門(mén)的特權(quán)檢查同調(diào)用門(mén)類似,對(duì)于軟件主動(dòng)發(fā)起的軟中斷,當(dāng)前特權(quán)級(jí) CPL 必須在門(mén)描述符 DPL 和門(mén)中目標(biāo)代碼段 DPL 之間蒿叠。這是為了防止位于 3 特權(quán)級(jí)下的用戶程序主動(dòng)調(diào)用某些只為內(nèi)核服務(wù)的例程东亦。
(a)如果是由軟中斷 int n, int3 和 into 引發(fā)的中斷滋捶,這些是用戶進(jìn)程中主動(dòng)發(fā)起的中斷饥侵,由用戶代碼 控制烁焙,處理器要檢查當(dāng)前特權(quán)級(jí) CPL 和門(mén)描述符 DPL,這是檢查進(jìn)門(mén)的特權(quán)下限施绎,如果 CPL 權(quán)限大于等 于 DPL溯革,即數(shù)值上 CPL~三門(mén)描述符 DPL,特權(quán)級(jí)“門(mén)檻”檢查通過(guò)谷醉,進(jìn)入下一步的“門(mén)框”檢查致稀。否則, 處理器拋出異常俱尼。
(b)這一步檢查特權(quán)級(jí)的上限(門(mén)框〉:處理器要檢查當(dāng)前特權(quán)級(jí) CPL 和門(mén)描述符中所記錄的選擇子 對(duì)應(yīng)的目標(biāo)代碼段 DPL抖单,如果 CPL 權(quán)限小于目標(biāo)代碼段 DPL,即數(shù)值上 CPL>目標(biāo)代碼段 DPL遇八,檢查通 過(guò)矛绘。 否則 CPL 若大于等于目標(biāo)代碼段 DPL,處理器將引發(fā)異常刃永,也就是說(shuō)货矮,除了用返回指令從高特權(quán)級(jí) 返回,特權(quán)轉(zhuǎn)移只能發(fā)生在由低向高斯够。 若中斷是由外部設(shè)備和異常引起的囚玫,只直接檢查 CPL 和目標(biāo)代碼段的 DPL,和上面的步驟 b)是一樣的雳刺,要求 CPL 權(quán)限小于目標(biāo)代碼段 DPL,即數(shù)值上 CPL >目標(biāo)代碼段 DPL裸违,否則處理器引發(fā)異常掖桦。 -
執(zhí)行中斷處理程序。 特權(quán)級(jí)檢查通過(guò)后供汛,將門(mén)描述符目標(biāo)代碼段選擇子加載到代碼段寄存器 cs 中枪汪,把門(mén)描述符中中斷處 理程序的偏移地址加載到 EIP,開(kāi)始執(zhí)行中斷處理程序怔昨。
由于 IDT 中全都是門(mén)描述符雀久,所以圖 7-7 的 IDT 中的“某門(mén)描述符”表示中斷門(mén)、陸阱門(mén)或任務(wù)門(mén)趁舀。 中斷發(fā)生后赖捌,eflags 中的NT位和 TF位會(huì)被置0。如果中斷對(duì)應(yīng)的門(mén)描述符是中斷門(mén)矮烹,標(biāo)志寄存器eflags 中的 E 位被自動(dòng)置 0越庇,避免中斷嵌套罩锐,即中斷處理過(guò)程中又來(lái)了個(gè)新的中斷,這是為防止在處理某個(gè)中斷 的過(guò)程中又來(lái)了個(gè)相同的中斷卤唉,即同一種中斷未處理完時(shí)又來(lái)了一個(gè)涩惑,這會(huì)導(dǎo)致一般保護(hù)性(GP)異常。 這表示默認(rèn)情況下桑驱,處理器會(huì)在無(wú)人打擾的方式下執(zhí)行中斷門(mén)描述符中的中斷處理例程竭恬。 若中斷發(fā)生時(shí)對(duì)應(yīng)的描述符是任務(wù)門(mén)或陸阱門(mén)的話, CPU 是不會(huì)將 E 位清 0 的熬的。 因?yàn)殛戁彘T(mén)主要用 于調(diào)試痊硕,它允許 CPU 響應(yīng)更高級(jí)別的中斷,所以允許中斷嵌套悦析。而對(duì)任務(wù)門(mén)來(lái)說(shuō)寿桨,這是執(zhí)行一個(gè)新任務(wù), 任務(wù)都應(yīng)該在開(kāi)中斷的情況下進(jìn)行强戴,否則就獨(dú)占 CPU 資源亭螟,操作系統(tǒng)也會(huì)由多任務(wù)退化成單任務(wù)了。 從中斷返回的指令是 iret骑歹,它從戰(zhàn)中彈出數(shù)據(jù)到寄存器 cs预烙、 eip、 eflags 等道媚,根據(jù)特權(quán)級(jí)是否改變扁掸,判 斷是否要恢復(fù)舊枝,也就是說(shuō)是否將戰(zhàn)中位于 SS_old 和 ESP_old 位直的值彈出到寄存 SS 和 esp最域。當(dāng)中斷 處理程序執(zhí)行完成返回后谴分,通過(guò) iret 指令從棋中恢復(fù) eflags 的內(nèi)容。
- 處理器提供了專門(mén)用于控制 E 位的指令镀脂,通過(guò)它牺蹄, IF 可以直接控制。指令
cli
使 IF 位為 0薄翅,這稱為關(guān)中斷沙兰,指令sti
使 E 位為 1,這稱為開(kāi)中斷翘魄。 - IF 位只能限制外部設(shè)備的中斷鼎天,對(duì)那些影響系統(tǒng)正常運(yùn)行的中斷都無(wú)效,如異常 exception暑竟,軟中斷斋射, 如 int n 等,不可屏蔽中斷 NMI 都不受 E 限制。
- 進(jìn)入中斷時(shí)要把
NT
位和TF
位置為 0绩鸣。 TF 表示 Trap Flag怀大,也就是陸阱標(biāo)志位,這用在調(diào)試環(huán)境中呀闻,當(dāng)TF
為 0 時(shí)表示禁止單步執(zhí)行化借,也就是說(shuō),進(jìn)入中斷后將 TF 直為 0捡多,表示不允許申斷處理程序單步執(zhí)行蓖康, 這是好理解的。
NT
位表示NestTaskFlag
垒手,即任務(wù)嵌套標(biāo)志位蒜焊,也就是用來(lái)標(biāo)記任務(wù)嵌套調(diào)用的情況。任務(wù)嵌套調(diào)用是指 CPU 將當(dāng)前正執(zhí)行的舊任務(wù)掛起科贬,轉(zhuǎn)去執(zhí)行另外的新任務(wù)泳梆,待新任務(wù)執(zhí)行完后, CPU 再回到舊任務(wù)繼續(xù)執(zhí)行榜掌。 為什么 CPU 執(zhí)行完舊任務(wù)后還能回到新任務(wù)呢优妙?
原因是在執(zhí)行新任務(wù)之前, CPU 做了兩件準(zhǔn)備工作憎账。
(1 )將舊任務(wù) TSS 選擇子寫(xiě)到了新任務(wù) TSS 中的“上一個(gè)任務(wù) TSS 的指針”字段中套硼。
(2)將新任務(wù)標(biāo)志寄存器 eflags 中的 NT 位置 l ,表示新任務(wù)之所以能夠執(zhí)行胞皱,是因?yàn)橛袆e的任務(wù)調(diào) 用了它邪意。
第(2)步中這個(gè)“別的任務(wù)”便是指 CPU 在第 1 步中寫(xiě)進(jìn)新任務(wù)自己 TSS 的“上一個(gè)任務(wù) TSS 的 指針” 字段中的值。 CPU 把新任務(wù)執(zhí)行完后還是要回去繼續(xù)執(zhí)行舊任務(wù)的反砌,怎樣回到舊任務(wù)呢雾鬼?
這也是通過(guò)iret
指令。 iret 指令 因此有了兩個(gè)功能宴树, 一是從中斷返回策菜,另外一個(gè)就是返回到調(diào)用自己執(zhí)行的那個(gè)舊任務(wù),這也相當(dāng)于執(zhí)行一個(gè)任 務(wù)森渐。對(duì)同一條iret
指令做入,CPU 是如何知道該從中斷返回冒晰,還是返回到舊任務(wù)繼續(xù)執(zhí)行呢同衣? 這就用到 NT 位了,當(dāng) CPU 執(zhí)行 iret 時(shí)壶运,它會(huì)去檢查 NT 位的值耐齐,如果 NT 位為 1,這說(shuō)明當(dāng)前任務(wù) 是被嵌套執(zhí)行的,因此會(huì)從自己 TSS 中“上一個(gè)任務(wù) TSS 的指針”字段中獲取舊任務(wù)埠况,然后去執(zhí)行該任 務(wù)耸携。如果 NT 位的值為 0,這表示當(dāng)前是在中斷處理環(huán)境下辕翰,于是就執(zhí)行正常的中斷退出流程夺衍。
這個(gè)還是編譯器實(shí)現(xiàn)為準(zhǔn),見(jiàn)下節(jié)
中斷發(fā)生時(shí)的壓棧
-
中斷時(shí)特權(quán)級(jí)發(fā)生變化的壓棧
- 中斷時(shí)特權(quán)級(jí)不發(fā)生變化的壓棧
 - 同類的指令還有
iretw
和iretd
, 16 位模式下用iretw
32 位模式下用iretd
喜命。iret
是iretw
和iretd
的簡(jiǎn)寫(xiě)沟沙,無(wú)論是在 16 位模式,還是在 32 位模式下編碼壁榕,都可以只用iret
指令矛紫,它是被編譯成iretw
,還是被編譯成iretd
牌里,取決于偽指令 BITS 所指明的字長(zhǎng)颊咬。 - 注意,如果中斷有錯(cuò)誤碼牡辽,處理器并不會(huì)主動(dòng)跳過(guò)它的位置喳篇,我們必須手動(dòng)將其跳過(guò),也就是說(shuō)催享,在準(zhǔn)備用
iret
指令返回時(shí)杭隙,當(dāng)前棧指針 esp 必須指向棧中備份的 EIP_old 所在的位置,這樣處理器才能將棧中的數(shù)據(jù)對(duì)號(hào)入座因妙,彈出到各自對(duì)應(yīng)的寄存器中痰憎。 - 注意,如果在返回時(shí)需要改變特權(quán)級(jí)攀涵,將會(huì)檢查數(shù)據(jù)段寄存器 DS铣耘、 ES、 FS 和 GS 的內(nèi)容以故,如果在它 們之中蜗细,某個(gè)寄存器中選擇子所指向的數(shù)據(jù)段描述符的 DPL 權(quán)限比返回后的 CPL ( CS.RPL) 高,即數(shù)值上 返回后的 CPL>數(shù)據(jù)段描述符的 DPL怒详,處理器將把數(shù)值 0 填充到相應(yīng)的段寄存器炉媒。原理是選擇子為 0 便指向 GDT 中第 0 個(gè)段描述符,該段描述符不可用昆烁,從而故意使處理器拋異常吊骤。 如果忘記了,可以參考從調(diào)用門(mén)返回時(shí)的部分静尼。
中斷錯(cuò)誤碼 ERROR_CODE
-
EXT
表示EXTernal event
白粉,即外部事件传泊,用來(lái) 指明中斷源是否來(lái)自處理器外部,如果中斷源是不
可屏蔽中斷NMI 或外部設(shè)備鸭巴, EXT 為 1眷细,否則為 0。 - IDT 表示選擇子是否指向中斷描述符表 IDT, IDT 位為 1鹃祖,則表示此選擇子指向中斷描述符表溪椎,否則指向全局描述符表 GDT 或局部描述符表 LDT。
- TI 和選擇子中 TI 是一個(gè)意思恬口,為 0 時(shí)用來(lái)指明選擇子是從 GDT 中檢索描述符池磁,為 1 時(shí)是從 LDT 中 檢索描述符。當(dāng)然楷兽,只有在 IDT 位為 0 時(shí) TI位才有意義地熄。
- 選擇子高 13 位索引就是選擇子中用來(lái)在表中索引描述符用的下標(biāo)。 高 16 位是保留位芯杀,全 0端考。
- 錯(cuò)誤碼本質(zhì)上就是描述符選擇子,通過(guò)低 3 位屬性來(lái)修飾此選擇子指向是哪個(gè)表中的哪個(gè)描述符揭厚。
可編程中斷控制器
- 一個(gè)8259A只可以管理8個(gè)中斷却特,INTEL處理器共支持256個(gè)中斷。為了多支持一些中斷設(shè)備筛圆,可以將多個(gè)8259A組合裂明,即官方術(shù)語(yǔ)
級(jí)聯(lián)
,有了級(jí)聯(lián)以后太援,每個(gè)8259A都被稱為1片闽晦。級(jí)聯(lián)時(shí)只能有一個(gè)主片master,其余的稱為從片slave提岔。若采用級(jí)聯(lián)的方法仙蛉,n片8259A可以支持7n+1個(gè)中斷源,(原理類似新交換機(jī)或插線板在原來(lái)的交換機(jī)上再引出一條線作拓展的計(jì)算)碱蒙,級(jí)聯(lián)一個(gè)從片荠瘪,要占用主片的一個(gè)IRQ接口。 -
個(gè)人電腦中只有兩片8259A芯片赛惩,級(jí)聯(lián)如圖
-
8259A芯片內(nèi)部結(jié)構(gòu)
一些信號(hào)和寄存器介紹如下
- INT: 8259A 選出優(yōu)先級(jí)最高的中斷請(qǐng)求后哀墓,發(fā)信號(hào)通知 CPU。
- INTA: INT Acknowledge喷兼,中斷響應(yīng)信號(hào)篮绰。 位于 8259A 中的 INTA 接收來(lái)自 CPU 的INTA 接口的 中斷響應(yīng)信號(hào)。
- IMR: Interrupt Mask Register褒搔,中斷屏蔽寄存器阶牍,寬度是 8 位,用來(lái)屏蔽某個(gè)外設(shè)的中斷星瘾。
- IRR: Interrupt Request Register走孽,中斷請(qǐng)求寄存器,寬度是 8 位琳状。它的作用是接受經(jīng)過(guò) IMR 寄存器過(guò) 濾后的中斷信號(hào)并鎖存磕瓷,此寄存器中全是等待處理的中斷,“相當(dāng)于” 8259A 維護(hù)的未處理中斷信號(hào)隊(duì)列念逞。
- PR: Priority Resolver困食,優(yōu)先級(jí)仲裁器。 當(dāng)有多個(gè)中斷同時(shí)發(fā)生翎承,或當(dāng)有新的中斷請(qǐng)求進(jìn)來(lái)時(shí)硕盹,將 它與當(dāng)前正在處理的中斷進(jìn)行比較,找出優(yōu)先級(jí)更高的中斷叨咖。
- ISR: In-Servi臼Register瘩例,中斷服務(wù)寄存器,寬度是8 位甸各。當(dāng)某個(gè)中斷正在被處理時(shí)垛贤,保存在此寄存器中。