1. 程式人生 > >(萊昂氏unix原始碼分析導讀-20)中斷、陷入的入口和出口

(萊昂氏unix原始碼分析導讀-20)中斷、陷入的入口和出口

陷入處理程式的入口都為“trap”(這裡是指一個彙編程式,而非PDP11指令);

中斷則不同。他們有不同的入口,如:

525     .=60^.                       當前地址設定為60 octal

526     klin; br4                      /(中斷向量地址為60,電傳打字機輸入的中斷處理程式)

527     klou; br4                      /(中斷向量地址為64,電傳打字機輸出的中斷處理程式)

但是,如果接著往下看,你會發現所有的中斷處理程式都指向了同一個入口“call”:

0557: .globl _klrint

0558: klin: jsr r0,call; _klrint

0559:

0560: .globl _klxint

0561: klou: jsr r0,call; _klxint

更進一步的,你會發現,陷入程式的入口“trap”在執行了少許操作之後,就會跳到“call”,

也就是說陷入和中斷的處理程式入口最終合二為一。


如果“前狀態”為user態,則“call”在785行跳到真正的處理程式:

0785: jsr pc,*(r0)+

否則,則會在0799行進行這樣的操作:

0799 jsr pc,*(r0)+

對陷入來說,這個處理程式必然是trap函式(2693c語言函式)——0762jsr指令將_trap

送入了r0

0762: jsr r0,call1; _trap

而中斷則為不同的中斷處理程式,如電傳打字機輸入:

0558: klin: jsr r0,call; _klrint      打字機輸入的中斷處理程式:klrint

對於“前狀態”為user態的程序來說,從中斷和陷入處理程式返回後,還會執行一項非常重要的操作,即

會檢查runrun標誌,如此時有更高優先順序的程序,則呼叫swtch()切換程序。因此,中斷(陷入)處理程式

為“前狀態為user態”的程序提供了一個程序切換的時機。

為何對“前狀態”為核心態的程式不提供程序切換的機會呢?前面其實已經說明了原因,

還記得那個原則末——減少核心態的程序切換,以減少核心資料結構衝突的可能。

最後,通過“rtt”指令恢復pc和PS,即回到中斷(陷入)前的情形。

萊昂的10.4小節對trapcall程式有很細緻的描述,但可能仍有部分讀者對Return部分有疑問。其實,最好的方法

是拿出紙筆,畫一畫前後的棧圖——你一定會一目瞭然。這裡,我給出一種呼叫情況的棧圖,以供參考:

【情況說明】:User態程序中斷,進入call例程  ---- 返回call例程----直接retrunuser態(runrun == 0

棧圖還能幫助我們理解Trap入口處那個詭異的操作(0756: mov PS,-4(sp))。

假設中斷髮生,中斷向量指向Trap,且nofault0

可見,自此TrapCall擁有了相同的棧結構,並開始複用後面的程式碼。

需要特別注意的是:

New PS low 5 bit,在trap例程中才有意義,可以用來區分中斷原因。

512     Trap; br7+0;                   /bus error

          513     Trap; br7+1;                   /illegal instruction

          514     Trap; br7+2;                   /bpt trace trap

          515     Trap; br7+3;   

          ….

顯然,不同的中斷使用不同的PS,而br7+n中的n即構成new PSlow 5 bit——即中斷原因。