什麼是中斷,為什麼要用中斷?

來源:互聯網
上載者:User
中斷解析
一、中斷是什麼

中斷的漢語解釋是半中間發生阻隔、停頓或故障而斷開。那麼,在電腦系統中,我們為什麼需要“阻隔、停頓和斷開”呢?

舉個日常生活中的例子,比如說我正在廚房用瓦斯燒一壺水,這樣就只能守在廚房裡,苦苦等著水開——如果水溢出來澆滅了瓦斯,有可能就要發生一場災難了。等啊等啊,外邊突然傳來了驚奇的叫聲“怎麼不關水龍頭?”於是我慚愧的發現,剛才接水之後只顧著抱怨這份無聊的差事,居然忘了這事,於是慌慌張張的沖向水管,三下兩下關了龍頭,聲音又傳到耳邊,“怎麼幹什麼都是這麼馬虎?”。伸伸舌頭,這件小事就這麼過去了,我落寞的眼神又落在了水壺上。

門外忽然又傳來了鏗鏘有力的歌聲,我最喜歡的古裝劇要開演了,真想奪門而出,然而,聽著水壺發出“咕嘟咕嘟”的聲音,我清楚:除非等到水開,否則沒有我享受人生的時候。

這個情境跟中斷有什麼關係呢?

如果說我專心致志等待水開是一個過程的話,那麼叫聲、電視裡傳出的音樂不都讓這個過程“半中間發生阻隔、停頓或故障而斷開”了嗎?這不就是活生生的“中斷”嗎?

在這個情境中,我是唯一具有處理能力的主體,不管是燒水、關水龍頭還是看電視,同一個時間點上我只能幹一件事情。但是,在我專心致志幹一件事情時,總有許多或緊迫或不緊迫的事情突然出現在面前,都需要去關注,有些還需要我停下手頭的工作馬上去處理。只有在處理完之後,方能回頭完成先前的任務,“把一壺水徹底燒開!”

中斷機制不僅賦予了我處理意外情況的能力,如果我能充分發揮這個機制的妙用,就可以“同時”完成多個任務了。回到燒水的例子,實際上,無論我在不在廚房,瓦斯灶總是會把水燒開的,我要做的,只不過是及時關掉瓦斯灶而已,為了這麼一個一秒鐘就能完成的動作,卻讓我死死地守候在廚房裡,在10分鐘的時間裡不停地看壺嘴是不是冒蒸氣,怎麼說都不划算。我決定安下心來看電視。當然,在有生之年,我都不希望讓廚房成為火海,於是我上了鬧鐘,10分鐘以後它會發出“尖叫”,提醒我爐子上的水燒開了,那時我再去關瓦斯也完全來得及。我用一個中斷訊號——鬧鈴——換來了10分鐘的歡樂時光,心裡不禁由衷地感歎:中斷機制真是個好東西。

正是由於中斷機制,我才能有條不紊地“同時”完成多個任務,中斷機制實質上協助我提高了並發“處理”能力。它也能給電腦系統帶來同樣的好處:如果在鍵盤按下的時候會得到一個中斷訊號,CPU就不必死守著等待鍵盤輸入了;如果硬碟讀寫完成後發送一個中斷訊號,CPU就可以騰出手來集中精力“服務福士”了——無論是人類敲打鍵盤的指尖還是來回讀寫介質的磁頭,跟CPU的處理速度相比,都太慢了。沒有中斷機制,就像我們苦守廚房一樣,電腦談不上有什麼平行處理能力。

跟人相似,CPU也一樣要面對紛繁蕪雜的局面——現實中的意外是無處不在的——有可能是使用者等得不耐煩,猛敲鍵盤;有可能是運算中碰到了0除數;還有可能網卡突然接收到了一個新的資料包。這些都需要CPU具體情況具體分析,要麼馬上處理,要麼暫緩響應,要麼置之不理。無論如何應對,都需要CPU暫停“手頭”的工作,拿出一種對策,只有在響應之後,方能回頭完成先前的使命,“把一壺水徹底燒開!”

先讓我們感受一下中斷機制對並發處理帶來的協助。

讓我們用程式來探討一下燒水問題,如果沒有“中斷”(注意,我們這裡只是模仿中斷的情境,實際上是用非同步事件——訊息——處理機制來展示中斷產生的效果。畢竟,在使用者空間沒有辦法與實際中斷產生直接聯絡,不過作業系統為使用者空間提供的非同步事件機制,可以看作是模仿中斷的產物),設計如下:

void StayInKitchen()

{

bool WaterIsBoiled = false;

while ( WaterIsBoiled != true )

{

bool VaporGavenOff = false;

if (VaporGavenOff )

WaterIsBoiled = true;

else

WaterIsBoiled = false;

}

// 關瓦斯爐

printf(“Close gas oven./n”);

// 一切安定下來,終於可以看電視了,10分鐘的寶貴時間啊,逝者如斯夫…

watching_tv();

return;

}

可以看出,整個流程如同我們前面描述的一樣,所有工作要順序執行,沒有辦法完成並發任務。

如果用“中斷”,在開始燒水的時候設定一個10分鐘的“鬧鈴”,然後讓CPU去看電視(有點難度,具體實現不在我們關心的範圍之內,留給讀者自行解決吧:>)。等鬧鐘響的時候再去廚房關爐子。

#i nclude

#i nclude

#i nclude

#i nclude

#i nclude

// 鬧鐘到時會執行此程式

void sig_alarm(int signo)

{

//關瓦斯爐

printf(“Close gas oven./n”);

}

void watching_tv()

{

while(1)

{

// 呵呵,悠哉悠哉

}

}

int main()

{

// 點火後設定定時中斷

printf(“Start to boil water, set Alarm”);

if (signal( SIGALRM, sig_alrm ) == SIG_ERR)

{

perror("signal(SIGALRM) error");

return -1;

}

// 然後就可以欣賞電視節目了

printf(“Watching TV!/n”);

watching_tv();

return 0;

}

這兩段程式都在使用者空間執行。第二段程式跟中斷也沒有太大的關係,實際上它只用了訊號機制而已。但是,通過這兩個程式的對比,我們可以清楚地看到非同步事件的處理機制是如何提升並發處理能力的。

Alarm定時器:alarm相當於系統中的一個定時器,如果我們調用alarm(5),那麼5秒鐘後就會“響起一個鬧鈴”(實際上靠訊號機制實現的,我們這裡不想深入細節,如果你對此高度興趣,請參考Richard Stevens不朽著作《Unix環境進階編程》)。在鬧鈴響起的時候會發生什麼呢?系統會執行一個函數,至於到底是什麼函數,系統允許程式自行決定。程式員編寫一個函數,並調用signal對該函數進行註冊,這樣一旦定時到來,系統就會調用程式員提供的函數(CallBack函數?沒錯,不過在這裡如何?並不關鍵,我們就不引入新的概念和細節了)。上面的例子裡我們提供的函數是sig_alarm,所做的工作很簡單,列印“關閉瓦斯灶”訊息。

上面的兩個例子很簡單,但很能說明問題,首先,它證明採用非同步訊息處理機制可以提高系統的並發處理能力。更重要的是,它揭示了這種處理機制的模式。使用者根據需要設計處理常式,並可以將該程式和特定的外來事件綁定起來,在外來事件發生時系統自動調用處理常式,完成相關工作。這種模式給系統帶來了統一的管理方法,也帶來無盡的功能擴充空間。

電腦系統實現中斷機制是非常複雜的一件工作,再怎麼說人都是高度智能化的生物,而電腦作為一個鐵疙瘩,沒有程式的教導就一事無成。而處理一個中斷過程,它受到的限制和需要學習的東西太多了。

首先,電腦能夠接收的外部訊號形式非常有限。中斷是由外部的輸入引起的,可以說是一種刺激。在燒水的情境中,這些輸入是叫聲和電視的音樂,我們這裡只以聲音為例。其實現實世界中能輸入人類CPU——大腦的訊號很多,映像、氣味一樣能被我們接受,人的資訊介面很完善。而電腦則不然,接受外部訊號的途徑越多,設計實現就越複雜,代價就越高。因此個人電腦(PC)給所有的外部刺激只留了一種輸入方式——特定格式的電訊號,並對這種訊號的格式、接入方法、回應程式法、處理步驟都做了規約(具體內容本文後面部分會繼續詳解),這種訊號就是中斷或中斷訊號,而這一整套機制就是中斷機制。

其次,電腦不懂得如何應對訊號。人類的大腦可以自行處理外部輸入,我從來不用去擔心鬧鐘響時會手足無措——走進廚房關瓦斯,這簡直是天經地義的事情,還用大腦想啊,小腿肚子都知道——可惜電腦不行,沒有程式,它就紋絲不動。因此,必須有機制保證外部中斷訊號到來後,有正確的程式在正確的時候被執行。

還有,電腦不懂得如何保持工作的持久性。我在看電視的時候如果去廚房關了瓦斯,回來以後能繼續將電視進行到底,不受太大的影響。而電腦則不然,如果放下手頭的工作直接去處理“意外”的中斷,那麼它就再也沒有辦法想起來曾經作過什麼,做到什麼程度了。自然也就沒有什麼“重操舊業”的機會了。這樣的處理方式就不是並發執行,而是東一榔頭,西一棒槌了。

那麼,通用的電腦系統是如何解決這些問題的呢?它是靠硬體和軟體配合來協同實現中斷處理的全過程的。我們將通過Intel X86架構的實現來介紹這一過程。

CPU執行完一條指令後,下一條指令的邏輯地址存放在cs和eip這對寄存器中。在執行新指令前,控制單元會檢查在執行前一條指令的過程中是否有中斷或異常發生。如果有,控制單元就會拋下指令,進入下面的流程:

1. 確定與中斷或異常關聯的向量i (0£i£255)

2. 尋找向量對應的處理常式

3. 儲存當前的“工作現場”,執行中斷或異常的處理常式

4. 處理常式執行完畢後,把控制權交還給控制單元

5. 控制單元恢複現場,返回繼續執行原程式

整個流程如所示:

 

圖一:中斷處理過程

讓我們深入這個流程,看看都有什麼問題需要面對。

1、異常是什麼概念?

在處理器執行到由於編程失誤而導致的錯誤指令(例如除數是0)的時候,或者在執行期間出現特殊情況(例如缺頁),需要靠作業系統來處理的時候,處理器就會產生一個異常。對大部分處理器體繫結構來說,處理異常和處理中斷的方式基本是相同的,x86架構的CPU也是如此。異常與中斷還是有些區別,異常的產生必須考慮與處理器時鐘的同步。實際上,異常往往被稱為同步中斷。

2、中斷向量是什嗎?

中斷向量代表的是中斷源——從某種程度上講,可以看作是中斷或異常的類型。中斷和異常的種類很多,比如說被0除是一種異常,缺頁又是一種異常,網卡會產生中斷,音效卡也會產生中斷,CPU如何區分它們呢?中斷向量的概念就是由此引出的,其實它就是一個被送通往CPU資料線的一個整數。CPU給每個IRQ分配了一個類型號,通過這個整數CPU來識別不同類型的中斷。這裡可能很多朋友會尋問為什麼還要弄個中斷向量這麼麻煩的東東?為什麼不直接用IRQ0~IRQ15就完了?比如就讓IRQ0為0,IRQ1為1……,這不是要簡單得多嗎?其實這裡體現了模組化設計規則,及節約規則。

首先我們先談談節約規則,所謂節約規則就是所使用的訊號線數越少越好,這樣如果每個IRQ都獨立使用一根資料線,如IRQ0用0號線,IRQ1用1號線……這樣,16個IRQ就會用16根線,這顯然是一種浪費。那麼也許馬上就有朋友會說:那麼只用4根線不就行了嗎?(2^4=16)。

這個問題,體現了模組設計規則。我們在前面就說過中斷有很多類,可能是外部硬體觸發,也可能是由軟體觸發,然而對於CPU來說中斷就是中斷,只有一種,CPU不用管它到底是由外部硬體觸發的還是由啟動並執行軟體本身觸發的,因為對於CPU來說,中斷處理的過程都是一樣的:中斷現行程式,轉到中斷服務程式處執行,回到被中斷的程式繼續執行。CPU總共可以處理256種中斷,而並不知道,也不應當讓CPU知道這是硬體來的中斷還是軟體來的中斷,這樣,就可以使CPU的設計獨立於中斷控制器的設計,這樣CPU所需完成的工作就很單純了。CPU對於其它的模組只提供了一種介面,這就是256個中斷處理向量,也稱為中斷號。由這些中斷控制器自行去使用這256個中斷號中的一個與CPU進行互動,比如,硬體中斷可以使用前128個號,軟體中斷使用後128個號,也可以軟體中斷使用前128個號,硬體中斷使用後128個號,這與CPU完全無關了,當你需要處理的時候,只需告訴CPU你用的是哪個中斷號就行,而不需告訴CPU你是來自哪兒的中斷。這樣也方便了以後的擴充,比如現在機器裡又加了一片8259晶片,那麼這個晶片就可以使用閒置中斷號,看哪一個空閑就使用哪一個,而不是必須要使用第0號,或第1號中斷號了。其實這相當於一種映射機制,把IRQ訊號映射到不同的中斷號上,IRQ的排列或說編號是固定的,但通過改變映射機制,就可以讓IRQ映射到不同的中斷號,也可以說調用不同的中斷服務程式。

3、什麼是中斷服務程式?

在響應一個特定中斷的時候,核心會執行一個函數,該函數叫做中斷處理常式(interrupt handler)或中斷服務程式(interrupt service routine(ISR))。產生中斷的每個裝置都有相應的中斷處理常式。例如,由一個函數專門處理來自系統時鐘的中斷,而另外一個函數專門處理由鍵盤產生的中斷。

一般來說,中斷服務程式要負責與硬體進行互動,告訴該裝置中斷已被接收。此外,還需要完成其他相關工作。比如說網路裝置的中斷服務程式除了要對硬體應答,還要把來自硬體的網路資料包拷貝到記憶體,對其進行處理後再交給合適的協議棧或應用程式。每個中斷服務程式根據其要完成的任務,複雜程度各不相同。

一般來說,一個裝置的中斷服務程式是它的裝置驅動程式(device driver)的一部分——裝置驅動程式是用於對裝置進行管理的核心代碼。

4、隔離變化

不知道您有沒有意識到,中斷處理前面這部分的設計是何等的簡單優美。人是高度智能化的,能夠對遇到的各種意外情況做有針對性的處理,電腦相比就差距甚遠了,它只能根據預定的程式進行操作。對於電腦來說,硬體支援的,只能是中斷這種電訊號傳播的方式和CPU對這種訊號的接收方法,而具體如何處理這個中斷,必須得靠作業系統實現。作業系統支援所有事先能夠預料到的中斷訊號,理論上都不存在太大的挑戰,但在作業系統安裝到電腦裝置上以後,肯定會時常有新的外圍裝置被加入系統,這可能會帶來安裝系統時根本無法預料的“意外”中斷。如何支援這種擴充,是整個系統必須面對的。

而硬體和軟體在這裡的協作,給我們帶來了完美的答案。當新的裝置引入新類型的中斷時,CPU和作業系統不用關注如何處理它。CPU只負責接收中斷訊號,並引用中斷服務程式;而作業系統提供預設的中斷服務——一般來說就是不理會這個訊號,返回就可以了——並負責提供介面,讓使用者通過該介面註冊根據裝置具體功能而編製的中斷服務程式。如果使用者註冊了對應於一個中斷的服務程式,那麼CPU就會在該中斷到來時調用使用者註冊的服務程式。這樣,在中斷來臨時系統需要如何操作硬體、如何?硬體功能這部分工作就完全獨立於CPU架構和作業系統的設計了。

而當你需要加入新裝置的時候,只需要告訴作業系統該裝置佔用的中斷號、按照作業系統要求的介面格式撰寫中斷服務程式,用作業系統提供的函數註冊該服務程式,裝置的中斷就被系統支援了。

中斷和對中斷的處理被解除了耦合。這樣,無論是你在需要加入新的中斷時,還是在你需要改變現有中斷的服務程式時、又或是取消對某個中斷支援的時候,CPU架構和作業系統都無需作改變。

5、儲存當前工作“現場”

在中斷處理完畢後,電腦一般來說還要回頭處理原先手頭正做的工作。這給中斷的概念帶來些額外的“內涵”。注一“回頭”不是指從頭再來重新做,而是要接著剛才的進度繼續做。這就需要在處理中斷訊號之前保留工作“現場”。“現場”這個詞比較晦澀,其實就是指一個資訊集,它能反映某個時間點上任務的狀態,並能保證按照這些資訊就能恢複任務到該狀態,繼續執行下去。再直白一點,現場不過就是一組寄存器值。而如何保護現場和恢複情境是中斷機制需要考慮的重點之一。

每個中斷處理都要經曆這個儲存和恢複過程,我們可以抽象出其中的步驟:

1. 儲存現場

2. 執行具體的中斷服務程式

3. 從中斷服務返回

4. 恢複現場

上面說過了,“現場”看似在不斷變化,沒有哪個瞬間相同。但實際上組成現場的要素卻不會有任何改變。也就是說,只要我們儲存了相關的寄存器狀態,現場就能儲存下來。而恢複“現場”就是重新載入這些寄存器。換句話說,對於任何一個中斷,保護現場和恢複現場所做的都是完全相同的操作。

既然操作相同,實現操作的過程和代碼就相同。減少代碼的冗餘是模組化設計的基本準則,實在沒有道理讓所有的中斷服務程式都重複實現這樣的功能,應該將它作為一種基本的結構由底層的作業系統或硬體完成。而對中斷的處理過程需要迅速完成,因此,Intel CPU的控制器就承擔了這個任務,非但如此,上面的所有步驟次序都被固化下來,由控制器驅動完成。儲存現場和恢複現場都由硬體自動完成,大大減輕了作業系統和裝置驅動程式的負擔。

6、硬體對中斷支援的細節

下面的部分,本來應該介紹8259、中斷控制器編程、中斷描述符表等內容,可是我看到了瀟寒寫的“保護模式下的8259A晶片編程及中斷處理探究”(見參考資料1),前人之述備矣,讀者直接讀它好了。
從外而內,Linux對中斷的支援

在Linux中,中斷處理常式看起來就是普普通通的C函數。只不過這些函數必須按照特定的型別宣告,以便核心能夠以標準的方式傳遞處理常式的資訊,在其他方面,它們與一般的函數看起來別無二致。中斷處理常式與其它核心功能的真正區別在於,中斷處理常式是被核心調用來響應中斷的,而它們運行於我們稱之為中斷內容相關的特殊上下文中。關於中斷上下文,我們將在後面討論。

中斷可能隨時發生,因此中斷處理常式也就隨時可能執行。所以必須保證中斷處理常式能夠快速執行,這樣才能保證儘可能快地恢複被中斷代碼的執行。因此,儘管對硬體而言,迅速對其中斷進行服務非常重要。但對系統的其它部分而言,讓中斷處理常式在儘可能短的時間內完成執行也同樣重要。

即使最精簡版的中斷服務程式,它也要與硬體進行互動,告訴該裝置中斷已被接收。但通常我們不能像這樣給中斷服務程式隨意減負,相反,我們要靠它完成大量的其它工作。作為一個例子,我們可以考慮一下網路裝置的中斷處理常式面臨的挑戰。該處理常式除了要對硬體應答,還要把來自硬體的網路資料包拷貝到記憶體,對其進行處理後再交給合適的協議棧或應用程式。顯而易見,這種運動量不會太小。

現在我們來分析一下Linux作業系統為了支援中斷機制,具體都需要做些什麼工作。

首先,作業系統必須保證新的中斷能夠被支援。電腦系統硬體留給外設的是一個統一的中斷訊號介面。它固化了中斷訊號的接入和傳遞方法,拿PC機來說,中斷機制是靠兩塊8259和CPU協作實現的。外設要做的只是把中斷訊號發送到8259的某個特定引腳上,這樣8259就會為此中斷分配一個標識——也就是通常所說的中斷向量,通過中斷向量,CPU就能夠在以中斷向量為索引的表——中斷向量表——裡找到中斷服務程式,由它決定具體如何處理中斷。(具體細節還請查閱參考資料1,對於為何採用這種機制,該資料有精彩描述)這是硬體規定的機制,軟體只能無條件服從。

因此,作業系統對新中斷的支援,說簡單點,就是維護中斷向量表。新的外圍裝置加入系統,首先得明確自己的中斷向量號是多少,還得提供自身中斷的服務程式,然後利用Linux的核心調用介面,把〈中斷向量號、中斷服務程式〉這對資訊填寫到中斷向量表中去。這樣CPU在接收到中斷訊號時就會自動調用中斷服務程式了。這種註冊操作一般是由裝置驅動程式完成的。

其次,作業系統必須提供給程式員簡單可靠的編程介面來支援中斷。中斷的基本流程前面已經講了,它會打斷當前進行中的工作去執行中斷服務程式,然後再回到先前的任務繼續執行。這中間有大量需要解決問題:如何保護現場、嵌套中斷如何處理等等,作業系統要一一化解。程式員,即使是驅動程式的開發人員,在寫中斷服務程式的時候也很少需要對被打斷的進程心存憐憫。(當然,出於提高系統效率的考慮,編寫驅動程式要比編寫使用者級程式多一些條條框框,誰讓我們頂著系統程式員的光環呢?)

作業系統為我們屏蔽了這些與中斷相關硬體機制打交道的細節,提供了一套精簡的介面,讓我們用極為簡單的方式實現對實際中斷的支援,Linux是怎麼完美的做到這一點的呢?

CPU對中斷處理的流程:

我們首先必須瞭解CPU在接收到中斷訊號時會做什麼。沒辦法,作業系統必須瞭解硬體的機制,不配合硬體就寸步難行。現在我們假定核心已被初始化,CPU在保護模式下運行。

CPU執行完一條指令後,下一條指令的邏輯地址存放在cs和eip這對寄存器中。在執行新指令前,控制單元會檢查在執行前一條指令的過程中是否有中斷或異常發生。如果有,控制單元就會拋下指令,進入下面的流程:

1.確定與中斷或異常關聯的向量i (0£i£255)。

2.籍由idtr寄存器從IDT表中讀取第i項(在下面的描述中,我們假定該IDT表項中包含的是一個中斷門或一個陷阱門)。

3.從gdtr寄存器獲得GDT的基地址,並在GDT表中尋找,以讀取IDT表項中的選擇符所標識的段描述符。這個描述符指定中斷或例外處理常式所在段的基地址。

4.確信中斷是由授權的(中斷)發生源發出的。首先將當前特權級CPL(存放在cs寄存器的低兩位)與段描述符(即DPL,存放在GDT中)的描述符特權級比較,如果CPL小於DPL,就產生一個“通用保護”異常,因為中斷處理常式的特權不能低於引起中斷的程式的特權。對於編程異常,則做進一步的安全檢查:比較CPL與處於IDT中的門描述符的DPL,如果DPL小於CPL,就產生一個“通用保護”異常。這最後一個檢查可以避免使用者應用程式訪問特殊的陷阱門或中斷門。

5.檢查是否發生了特權級的變化,也就是說, CPL是否不同於所選擇的段描述符的DPL。如果是,控制單元必須開始使用與新的特權級相關的棧。通過執行以下步驟來做到這點:

a.讀tr寄存器,以訪問運行進程的TSS段。

b.用與新特權級相關的棧段和棧指標的正確值裝載ss和esp寄存器。這些值可以在TSS中找到(參見第三章的“任務狀態段”一節)。

c.在新的棧中儲存ss和esp以前的值,這些值定義了與舊特權級相關的棧的邏輯地址。

6.如果故障已發生,用引起異常的指令地址裝載cs和eip寄存器,從而使得這條指令能再次被執行。

7.在棧中儲存eflag、cs及eip的內容。

8.如果異常產生了一個硬性錯誤碼,則將它儲存在棧中。

9.裝載cs和eip寄存器,其值分別是IDT表中第i項門描述符的段選擇符和位移量域。這些值給出了中斷或者例外處理常式的第一條指令的邏輯地址。

控制單元所執行的最後一步就是跳轉到中斷或者例外處理常式。換句話說,處理完中斷訊號後,控制單元所執行的指令就是被選中的處理常式的第一條指令。

中斷或異常被處理完後,相應的處理常式必須產生一條iret指令,把控制權轉交給被中斷的進程,這將迫使控制單元:

1.用儲存在棧中的值裝載cs、eip、或eflag寄存器。如果一個硬性錯誤碼曾被壓入棧中,並且在eip內容的上面,那麼,執行iret指令前必須先彈出這個硬性錯誤碼。

2.檢查處理常式的CPL是否等於cs中最低兩位的值(這意味著被中斷的進程與處理常式運行在同一特權級)。如果是,iret終止執行;否則,轉入下一步。

3. 從棧中裝載ss和esp寄存器,因此,返回到與舊特權級相關的棧。

4. 檢查ds、es、fs及gs段寄存器的內容,如果其中一個寄存器包含的選擇符是一個段描述符,並且其DPL值小於CPL,那麼,清相應的段寄存器。控制單元這麼做是為了禁止使用者態的程式(CPL=3)利用核心以前所用的段寄存器(DPL=0)。如果不清這些寄存器,懷有惡意的使用者程式就可能利用它們來訪問核心地址空間。

再次,作業系統必須保證中斷資訊能夠高效可靠的傳遞

注一:那麼PowerOff(關機)算不算中斷呢?如果從字面上講,肯定符合漢語對中斷的定義,但是從訊號格式、處理方法等方面來看,就很難符合我們的理解了。Intel怎麼說的呢?該中斷沒有採用通用的中斷處理機制。那麼到底是不是中斷呢?我也說不上來:(

注二:更詳細的內容和其它一些注意事項請參考核心原始碼包中Documentations/rtc.txt

注三:之所以這裡使用彙編而不是C來實現這些函數,是因為C編譯器會在函數的實現中推入額外的棧資訊。而CPU在中斷來臨時儲存和恢複現場都按照嚴格的格式進行,一個位元組的變化都不能有。

參考資料

1 “保護模式下的8259A晶片編程及中斷處理探究” 瀟寒 哈工大純C論壇 http://purec.binghua.com/Article/ShowArticle.asp?ArticleID=91

2 “80x86 IBM PC及相容電腦(卷I和卷II):組合語言、設計與介面技術” Muhammad Ali Mazidi等著 張波等譯 清華大學出版社

3 “編寫作業系統之鍵盤互動的實現” 瀟寒 哈工大純C論壇 http://purec.binghua.com/Article/ShowArticle.asp?ArticleID=104  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.