中斷、異常、trap 的區別

【1】無論是中斷,還是異常和陷阱,對應的處理函數,一般都可以稱其爲中斷服務程序ISR,

           都只是一個函數 具體函數裏面要做什麼事情,是由你寫程序的人決定的。 

【2】 比如中斷中處理對應的事情,異常中自己決定如何響應出現的異常,陷阱中決定做什麼事情。



【3】    中斷:是爲了設備與CPU之間的通信。典型的有如服務請求,任務完成提醒等。比如我們熟知的時鐘中斷,硬盤讀寫服務請求中斷。中斷的發生與系統處在用戶態還是在內核態無關,只決定於EFLAGS寄存器的一個標誌位。我們熟悉的sti, cli兩條指令就是用來設置這個標誌位,然後決定是否允許中斷。在單個CPU的系統中,這也是保護臨界區的一種簡便方法。中斷是異步的,因爲從邏輯上來說,中斷的產生與當前正在執行的進程無關。事實上,中斷是如此有用,Linux用它來統計時鐘,進行硬盤讀寫等。
【4】   異常:異常是由當前正在執行的進程產生。異常包括很多方面,有出錯(fault),有陷入(trap),也有可編程異常(programmable exception)。出錯(fault)和陷入(trap)最重要的一點區別是他們發生時所保存的EIP值的不同。出錯(fault)保存的EIP指向觸發異常的那條指令;而陷入(trap)保存的EIP指向觸發異常的那條指令的下一條指令。因此,當從異常返回時,出錯(fault)會重新執行那條指令;而陷入(trap)就不會重新執行。這一點實際上也是相當重要的,比如我們熟悉的缺頁異常(page fault),由於是fault,所以當缺頁異常處理完成之後,還會去嘗試重新執行那條觸發異常的指令(那時多半情況是不再缺頁)。陷入的最主要的應用是在調試中,被調試的進程遇到你設置的斷點,會停下來等待你的處理,等到你讓其重新執行了,它當然不會再去執行已經執行過的斷點指令。
【5】   可編程中斷:這類中斷可由編程者用int指令來觸發。在Linux中,使用了一個,也是唯一的一個可編程中斷,就是int 0x80系統調用。硬件對可編程中斷的處理與對trap的處理類似,即從這類異常返回時也是返回到觸發異常的下一條指令。關於可編程中斷,還有另外一種說法:軟件中斷(software interrupt),其實是一個意思。


8086/8088把中斷分爲內部中斷和外部中斷兩大類。爲了支持多任務和虛擬存儲器等功能,80386把外部中斷稱爲“中斷”,把內部中斷稱爲“異常”。與8086/8088一樣,80386通常在兩條指令之間響應中斷或異常。80386最多處理256種中斷或異常。     
  1.中斷   
          對80386而言,中斷是由異步的外部事件引起的。外部事件及中斷響應與正執行的指令沒有關係。通常,中斷用於指示I/O設備的一次操作已完成。與8086/8088一樣,80386有兩根引腳INTR和NMI接受外部中斷請求信號。INTR接受可屏蔽中斷請求。NMI接受不可屏蔽中斷請求。在80386中,標誌寄存器EFLAGS中的IF標誌決定是否屏蔽可屏蔽中斷請求。     


4.6.7 中斷描述符表

      中斷描述符表(Interrupt Descriptor Table,IDT)將每個異常或中斷向量分別與它們的處理過程聯繫起來。與GDT和LDT表類似,IDT也是由8字節長描述符組成的一個數組。與GDT 不同的是,表中第1項可以包含描述符。爲了構成IDT表中的一個索引值,處理器把異常或中斷的向量號乘以8。因爲最多隻有256箇中斷或異常向量,所以 IDT無需包含多於256個描述符。IDT中可以含有少於256個描述符,因爲只有可能發生的異常或中斷才需要描述符。不過IDT中所有空描述符項應該設置其存在位(標誌)爲0。

IDT表可以駐留在線性地址空間的任何地方,處理器使用IDTR寄存器來定位IDT表的位置。這個寄存器中含有IDT表32位的基地址和16位的長度(限長)值,如圖4-26所示。IDT表基地址應該對齊在8字節邊界上以提高處理器的訪問效率。限長值是以字節爲單位的IDT表的長度。

                                                                
                                                                             圖4-26 中斷描述符表IDT和寄存器IDTR

      LIDT和SIDT指令分別用於加載和保存IDTR寄存器的內容。LIDT指令用於把內存中的限長值和基地址操作數加載到IDTR寄存器中。該指令僅能由當前特權級CPL是0的代碼執行,通常被用於創建IDT時的操作系統初始化代碼中。SIDT指令用於把IDTR中的基地址和限長內容複製到內存中。該指令可在任何特權級上執行。

如果中斷或異常向量引用的描述符超過了IDT的界限,處理器會產生一個一般保護性異常。

4.6.8 IDT描述符

        IDT表中可以存放3種類型的門描述符:中斷門(Interrupt gate)描述符、陷阱門(Trap gate)描述符、任務門(Task gate)描述符。

圖4-27給出了這三種門描述符的格式。中斷門和陷阱門含有一個長指針(即段選擇符和偏移值),處理器使用這個長指針把程序執行權轉移到代碼段中異常或中斷的處理過程中。這兩個段的主要區別在於處理器操作EFLAGS寄存器IF標誌上。IDT中任務門描述符的格式與GDT和LDT中任務門的格式相同。任務門描述符中含有一個任務TSS段的選擇符,該任務用於處理異常或中斷。

                                                  
 圖4-27 中斷門、陷阱門和任務門描述符格式


4.6.9 異常與中斷處理

       處理器對異常和中斷處理過程的調用操作方法與使用CALL指令調用程序過程和任務的方法類似。當響應一個異常或中斷時,處理器使用異常或中斷的向量作爲IDT表中的索引。如果索引值指向中斷門或陷阱門,則處理器使用與CALL指令操作調用門類似的方法調用異常或中斷處理過程。如果索引值指向任務門,則處理器使用與CALL指令操作任務門類似的方法進行任務切換,執行異常或中斷的處理任務。

異常或中斷門引用運行在當前任務上下文中的異常或中斷處理過程,如圖4-28所示。門中的段選擇符指向GDT或當前LDT中的可執行代碼段描述符。門描述符中的偏移字段指向異常或中斷處理過程的開始處。

                                                  
                                                                                      圖4-28 中斷過程調用

當處理器執行異常或中斷處理過程調用時會進行以下操作:

(1)如果處理過程將在高特權級(如0級)上執行時就會發生堆棧切換操作。堆棧切換過程如下:

       處理器從當前執行任務的TSS段中得到中斷或異常處理過程使用的堆棧的段選擇符和棧指針(例如tss.ss0、tss.esp0)。然後處理器會把被中斷程序(或任務)的棧選擇符和棧指針壓入新棧中,如圖4-29所示。

                                                         
                                                            圖4-29 轉移到中斷處理過程時堆棧的使用方法

      接着處理器會把EFLAGS、CS和EIP寄存器的當前值也壓入新棧中。如果異常會產生一個錯誤號,那麼該錯誤號也會被最後壓入新棧中。

(2)如果處理過程將在被中斷任務同一個特權級上運行,那麼:

      處理器把EFLAGS、CS和EIP寄存器的當前值保存在當前堆棧上。如果異常會產生一個錯誤號,那麼該錯誤號也會被最後壓入新棧中。

爲了從中斷處理過程中返回,處理過程必須使用IRET指令。IRET指令與RET指令類似,但IRET還會把保存的寄存器內容恢復到EFLAGS 中。不過只有當CPL是0時纔會恢復EFLAGS中的IOPL字段,並且只有當CPL不大於IOPL時,IF標誌纔會被改變。 如果當調用中斷處理過程時發生了堆棧切換,那麼在返回時IRET指令會切換到原來的堆棧。

(1)異常和中斷處理過程的保護

       異常和中斷處理過程的特權級保護機制與通過調用門調用普通過程類似。處理器不允許把控制轉移到比CPL更低特權級代碼段的中斷處理過程中,否則將產生一個一般保護性異常。另外,中斷和異常的保護機制在以下方面與一般調用門過程不同:

因爲中斷和異常向量沒有RPL,因此在隱式調用異常和中斷處理過程時不會檢查RPL。

只有當一個異常或中斷是由INT n、INT 3或INT 0指令產生時,處理器纔會檢查中斷或陷阱門中的DPL。此時CPL必須小於或等於門的DPL。這個限制可以防止運行在特權級3的應用程序使用軟件中斷訪問重要的異常處理過程,例如頁錯誤處理過程,假設這些處理過程已被存放在更高特權級的代碼段中。對於硬件產生的中斷和處理器檢測到的異常,處理器會忽略中斷門和陷阱門中的DPL。

因爲異常和中斷通常不會定期發生,因此這些有關特權級的規則有效地增強了異常和中斷處理過程能夠運行的特權級限制。我們可以利用以下技術之一來避免違反特權級保護:

異常或中斷處理程序可以存放在一個一致性代碼段中。這個技術可以用於只需訪問堆棧上數據的處理過程(如除出錯異常)。如果處理程序需要數據段中的數據,那麼特權級3必須能夠訪問這個數據段。但這樣一來就沒有保護可言了。

處理過程可以放在具有特權級0的非一致代碼段中。這種處理過程總是可以執行的,與被中斷程序或任務的當前特權級CPL無關。

(2)異常或中斷處理過程的標誌使用方式

        當通過中斷門或陷阱門訪問一個異常或中斷處理過程時,處理器會在把EFLAGS寄存器內容保存到堆棧上之後清除EFLAGS中的TF標誌。清除TF標誌可以防止指令跟蹤影響中斷響應。而隨後的IRET指令會用堆棧上的內容恢復EFLAGS的原TF標誌。

中斷門與陷阱門唯一的區別在於處理器操作EFLAGS寄存器IF標誌的方法。當通過中斷門訪問一個異常或中斷處理過程時,處理器會復位IF標誌以防止其他中斷干擾當前中斷處理過程。隨後的IRET指令則會用保存在堆棧上的內容恢復EFLAGS寄存器的IF標誌。而通過陷阱門訪問處理過程並不會影響 IF標誌。

(3)執行中斷處理過程的任務

        當通過IDT表中任務門訪問異常或中斷處理過程時,就會導致任務切換。從而可以在一個專用任務中執行中斷或異常處理過程。IDT表中的任務門引用 GDT中的TSS描述符。切換到處理過程任務的方法與普通任務切換一樣。由於本書討論的Linux操作系統沒有使用這種中斷處理方式,因此這裏不再贅述。

4.6.10 中斷處理任務

       當通過IDT中任務門來訪問異常或中斷處理過程時就會導致任務切換。使用單獨的任務來處理異常或中斷有如下好處:

被中斷程序或任務的完整上下文會被自動保存。

在處理異常或中斷時,新的TSS可以允許處理過程使用新特權級0的堆棧。在當前特權級0的堆棧已毀壞時如果發生了一個異常或中斷,那麼在爲中斷過程提供一個新特權級0的堆棧條件下,通過任務門訪問中斷處理過程能夠防止系統崩潰。

通過使用單獨的LDT給中斷或異常處理任務獨立的地址空間,可以把它與其他任務隔離開來。

使用獨立任務處理異常或中斷的不足之處是:在任務切換時必須對大量機器狀態進行保存,使得它比使用中斷門的響應速度要慢,導致中斷延時增加。

IDT中的任務門會引用GDT中的TSS描述符,如圖4-30所示。切換到句柄任務的過程與普通任務切換過程相同。到被中斷任務的反向鏈接會被保存在句柄任務TSS的前一任務鏈接字段中。如果一個異常會產生一個出錯碼,則該出錯碼會被複制到新任務堆棧上。

                                               
                                                                               圖4-30 中斷處理任務切換

當異常或中斷句柄任務用於操作系統中時,實際上有兩種分派調度任務的機制:操作系統軟件調度和處理器中斷機制的硬件調度。使用軟件調度方法時需要考慮到中斷開啓時採用中斷處理任務。


  1. 中斷信號的作用.
    1. 使CPU轉而去運行正常控制流之外的代碼.爲了它.就要在內核態堆棧保存程序計數器的當前值(eip和cs寄存器).並把與中斷類型相關的一個地址放在程序計數器.
    2. 中斷處理與進程切換的差異:由中斷或異常處理程序執行的代碼不是一個進程,而是內核控制路徑.代表中斷髮生時正在運行的進程執行.其比進程"輕".
  2. 中斷和異常
    1. 中斷:
      1. 可屏蔽中斷(maskable): I/O設備發出的中斷請求(irq)都屬於.可處於兩種狀態:屏蔽的/非屏蔽的.
      2. 非屏蔽中斷(nonmaskable): 只有幾個危急事件才引起.總是由CPU辨認.
    2. 異常:
      1. 處理器探測異常:當CPU執行指令時探測到一個反常條件所產生的異常. 根據保存在eip寄存器中的值,分爲3種; 1)故障(fault):通常可以被糾正.eip中保存的是引起故障的指令地址.糾正後會重新執行該條指令. ; 2)陷阱(trap):在陷阱指令執行後立刻報告.內核把控制器返回給程序後可以繼續他的執行而不失連貫性. eip保存的是隨後要執行的指令地址.只有當沒有必要重新執行已終止的指令時(通常爲了調試程序)時才觸發陷阱. ; 3)異常中止(abort):不能在eip中保存引起異常的指令所在的確切位置.用於報告嚴重的錯誤.異常中止處理程序會強制受影響的進程終止.
      2. 編程異常: 在編程者發出請求時發生.將其作爲陷阱來處理.也叫軟中斷.用途:1)執行系統調用.2)給調試程序通報一個特定的事件.
    3. 每個中斷和異常由0~255之間的一個數來標示.稱爲向量(vector).只有可屏蔽中斷的向量可以通過編程改變.其餘都是固定的.  
    4. IRQ和中斷:能發出中斷的設備都有一個IRQ的輸出線.所有IRQ線都與一個可編程中斷控制器(PIC)的硬件電路的輸入引腳相連.可以有選擇地禁止每條IRQ線.可對PIC編程從而禁止IRQ.禁止的中斷不丟失.一旦激活,PIC就把他們發送到CPU.該特性運行中斷處理程序逐次處理同一類型的IRQ.
    5. 爲了發揮SMP體系的並行性,能夠把中斷傳遞給每個CPU很重要.所以引入了I/O高級可編程控制器(I/O APIC)的組件.所有CPU都含有一個本地APIC,通過APIC總線(在系統總線上)連接到外部的I/O APIC.還支持CPU產生處理器間中斷(IPI),可以利用它來在CPU之間交換消息.
    6. 中斷描述符表:IDT是一個系統表,它與每一箇中斷或異常向量相聯繫.每一個向量在表中有相應的中斷或異常處理程序的入口地址.最多需要256*8=2048字節來存放IDT. idtr寄存器指定IDT的線性基地址及其最大長度,從而使IDT可以位於內存中的任何地方.分爲3種類型: 1)任務門:信號發生時,必須取代當前進程的那個進程的TSS選擇符存放在任務門中. ;2)中斷門:包含段選擇符和處理程序的段內偏移量.當CPU控制權轉移到一個適當的斷後,清除IF標誌來關閉將來會發生的可屏蔽中斷 ;3)陷阱門:與中斷門相似,但控制權傳遞到一個適合的CPU時不修改IF標誌.  Linux利用中斷門處理中斷,利用陷阱門處理異常.注意: "Double fault"異常是唯一由任務們處理的異常.表示一種內核錯誤.
  3. 中斷和異常處理程序的嵌套執行.
    1. 必須保證中斷處理程序永不阻塞,即中斷處理程序運行期間不能發生進程切換.因爲嵌套的內核控制路徑恢復執行時需要的數據都存放在當前線程的內核態堆棧上.
    2. 一箇中斷處理程序可以搶佔其他的中斷處理程序和異常處理程序.異常處理程序從不搶佔中斷處理程序.
  4. 初始化中斷描述符表
    1. 過程: 1)在初始化系統時把IDT表的初始地址裝入idtr寄存器,並初始化表中的每一項.; 2)int指令用於在用戶態進程發出一箇中斷信號,爲了防止模擬非法的中斷,將門描述符的DPL=0.; 3)在用戶態進程必須要能夠發出一個編程異常時,將門的SPL=3。
    2. Linux中的分類: 中斷門(DPL=0,所有LInux中斷處理程序都通過中斷門激活,並限制在內核態); 系統門(DPL=3,用來激活3個linux異常處理程序); 系統中斷門(DPL=3,激活int3的異常處理程序); 陷阱門(DPL=0,激活大部分的異常處理程序); 任務門(DPL=0,"Double Fault的異常處理).
    3. idt的初始化分爲兩步:1)將256個表項用同一個中斷門(即指向ignore_int()中斷處理程序:其是一個空的處理程序)來填充.2)用有意義的陷阱和中斷處理程序來代替空處理程序.
  5. 異常處理
    1. 大部分異常都解釋成爲出錯條件.當異常發生時,內核向引起異常的進程發送一個信號向它通知一個反常條件.
    2. 特殊情況: 1)"Device not availeble" 2)"Page Fault"該異常推遲給進程分配新的頁框,直到不能再推遲位置.
    3. 異常處理程序的標準結構: 1)在內核態堆棧中保存大多數寄存器的內容; 2)用C函數處理異常; 3)通過ret_from_exception函數從異常處理程序退出.
  6. 中斷處理
    1. 由於一個進程被掛起好久後中斷纔到達,因此一個完全無關的進程可能正在運行.所以發送信號給當前進程是無用的.
    2. 中斷處理依賴於中斷類型:1)I/O中斷(查詢設備以確定適當的操作過程); 2)時鐘中斷(該中斷告訴內核一個固定的時間間隔已經過去,作爲I/O中斷處理) ;3)處理器間中斷.
    3. I/O中斷處理:要能給多個設備同時提供服務.實現: 1)IRQ共享(每個ISR(中斷服務例程)是一個與單獨設備(共享IRQ線)相關的函數,因爲無法預知那個特定的設備產生IRQ,所以,中斷處理程序執行多個ISR,以驗證它的設備是否需要關注,如果是,當設備產生中斷時就執行所需的操作); 2)IRQ動態分配(一條IRQ線在可能的最後時刻才與一個設備相關聯.這樣,即使幾個設備並不共享IRQ線,但同一IRQ向量也可以由這幾個設備在不同時刻使用).
      1. 一箇中斷處理程序正在執行時,相應的IRQ線上發出的信號被暫時忽略; 中斷處理程序所代表的進程必須是出於Task_Running態的; 其不能執行任何阻塞過程.
      2. 中斷要執行的操作: 1)緊急的(在禁止可屏蔽中斷下立即執行); 2)非緊急的(在開中斷下立即執行); 3)非緊急可延遲的(由獨立的函數執行).
      3. 步驟:1)在內核態堆棧中保存IRQ的值和寄存器的內容; 2)爲正在給IRQ線服務的PIC發送一個應答來允許PIC進一步發出中斷; 3)執行共享這個IRQ的所有設備的ISR; 4)跳到ret_from_intr()的地址後終止.
      4. IRQ數據結構: 1)意外中斷:中斷內核沒有處理的中斷.原因是與某個IRQ線相關的ISR不存在或者與某個中斷線相關的所有例程都識別不出來.當一條IRQ線上的意外中斷次數過多時,就禁用這條IRQ線. 2)
      5. IRQ在多CPU系統上的分發:對稱多處理器模型(SMP).一般情況下,內核能夠公平地在CPU間分發中斷.但是在某些情況下,Linxu需要使用kirqd的內核線程來糾正IRQ的自動分配.其利用了CPU的IRQ親和力:通過修改I/O APIC的中斷重定向表表項,可以吧中斷信號發送到某個特定的CPU上.
    4. CPU間中斷處理:IPI不通過IRQ線傳輸,而是作爲信號直接放在連接所有CPU本地APIC總線上. 類型: 1)Call_Function_Vector(發往不包含發送者的所有CPU,強制這些CPU運行發送者傳遞過來的函數). 2)Reschedule_Vector(從中斷返回後,所有的重新調度都自動運行); 3)Invalidate_TLB_Vector(強制TLB無效,來刷新CPU的TLB).
  7. 軟中斷及tasklet:
    1. 可延遲中斷可以在開中斷的情況下執行.把可延遲中斷從中斷處理程序中抽出來有助於使內核保持較短的響應時間.Linux通過兩種非緊迫,可中斷內核函數:1)可延遲函數;2)通過工作隊列來執行的函數.
    2. tasklet是在軟中斷之上實現的.軟中斷的分配是靜態的,tasklet的分配和初始化是在運行時.軟中斷是可重入函數並使用自旋鎖來保護數據,其實可以並行在多CPU上執行的,tasklet總是串行執行,但是不同類型的tasklet可以併發執行,其不必是可重入的.四種操作:1)初始化;2)激活;3)屏蔽;4)執行.激活和執行被綁定在一個CPU上,雖然可以更好地利用CPU的Cache,但是有潛在的危險性(一個CPU很忙,但其他的很閒).
    3. 軟中斷:使用下標(共6個)來表示優先級.softirq_action[32]  softirq_vec數組.優先級是下標,所以只有前6元素個有效.另外,thread_info中有一個preempt_count字段來跟蹤內核搶佔和內核控制路徑的嵌套.
    4. 每個CPu都有自己的ksoftirqd/n內核線程.其爲了解決以下問題:軟中斷函數可以重新激活自己,軟中斷的連續高流量可能會產生問題.不然就要選擇以下兩種之一的策略:1)忽略do_softirq()運行時新出現的軟中斷,此種情況的等待是不可接受的;2)不斷地重新檢查掛起的軟中斷,這種情況下,do_softirq()函數就會一直不返回,用戶態程序實際上停止執行.解決:do_softirq()函數確定哪些軟中斷是掛起的,並執行他們的韓素華.如果已經執行的軟中斷又被激活,則do_softirq()喚醒內核線程並終止.內核線程有較低的優先級,因此用戶程序有就會運行.但是,如果機器空閒(沒有用戶態程序需要運行時),掛起的軟中斷就很快被執行.
    5. tasklet:是I/O驅動程序中實現可延遲函數的首選.
  8. 工作隊列
    1. 用來代替任務隊列.允許內核函數被激活,而且稍後由一種叫做工作者線程的特殊內核線程來執行.
    2. 可延遲函數運行在中斷上下文中,而工作隊列中的函數運行在進程上下文中.執行可阻塞函數的方式是在進程上下文中運行,因爲在中斷上下文中不可能發生進程切換.兩者都不能訪問進程的用戶態地址空間.

          外部硬件在通過INTR發出中斷請求信號的同時,還要向處理器給出一個8位的中斷向量。處理器在響應可屏蔽中斷請求時,讀取這個由外部硬件給出的中斷向量號。處理器對這個中斷向量號並沒有規定。但在具體的微機系統中,系統必須通過軟件和硬件的配合設置,使得給出的這個中斷向量號不僅與外部中斷源對應,而且要避免中斷向量號使用衝突情況的出現。可編程中斷控制器芯片8259A可配合80386工作,能夠根據設置向處理器提供上述中斷向量號,還能處理中斷請求的優先級。每個8259A芯片可以支持8路中斷請求信號,如果使用9個8259A芯片(一個主片,8個從片),就可使80386在單個引腳INTR上接受多達64箇中斷源的中斷請求信號。     
          處理器不屏蔽來自NMI的中斷請求。處理器在響應NMI中斷時,不從外部硬件接收中斷向量號。與8086/8088一樣,在80386中,不可屏蔽中斷所對應的中斷向量號固定爲2。爲了不可屏蔽中斷的嵌套,每當接受一個NMI中斷,處理器就在內部屏蔽了再次響應NMI,這一屏蔽過程直到執行中斷返回指令IRET後才結束。所以,NMI處理程序應以IRET指令結束。     
  2.異常   
          異常是80386在執行指令期間檢測到不正常的或非法的條件所引起的。異常與正執行的指令有直接的聯繫。例如,執行除法指令時,除數等於0。再如,執行指令時發現特權級不正確。當發生這些情況時,指令就不能成功完成。軟中斷指令“INT   n”和“INTO”也歸類於異常而不稱爲中斷,這是因爲執行這些指令產生異常事件。     
          80386識別多種不同類別的異常,並賦予每一種類別以不同的中斷向量號。異常發生後,處理器就象響應中斷那樣處理異常。即根據中斷向量號,轉相應的中斷處理程序。把這種中斷處理程序稱爲異常處理程序可能更合適。     
          根據引起異常的程序是否可被恢復和恢復點不同,把異常進一步分類爲故障(Fault)、陷阱(Trap)和中止(Abort)。我們把對應的異常處理程序分別稱爲故障處理程序、陷阱處理程序和中止處理程序。     
          故障是在引起異常的指令之前,把異常情況通知給系統的一種異常。80386認爲故障是可排除的。當控制轉移到故障處理程序時,所保存的斷點CS及EIP的值指向引起故障的指令。這樣,在故障處理程序把故障排除後,執行IRET返回到引起故障的程序繼續執行時,剛纔引起故障的指令可重新得到執行。這種重新執行,不需要操作系統軟件的額外參與。故障的發現可能在指令開始執行之前,也可能在指令執行期間。如果在指令執行期間檢測到故障,那麼中止故障指令,並把指令的操作數恢復爲指令開始執行之前的值。這可保證故障指令的重新執行得到正確的結果。例如,在一條指令的執行期間,如果發現段不存在,那麼停止該指令的執行,並通知系統產生段故障,對應的段故障處理程序可通過加載該段的方法來排除故障,之後,原指令就可成功執行,至少不再發生段不存在的故障。     
          陷阱是在引起異常的指令之後,把異常情況通知給系統的一種異常。當控制轉移到異常處理程序時,所保存的斷點CS及EIP的值指向引起陷阱的指令的下一條要執行的指令。下一條要執行的指令,不一定就是下一條指令。因此,陷阱處理程序並不是總能根據保存的斷點,反推確定出產生異常的指令。在轉入陷阱處理程序時,引起陷阱的指令應正常完成,它有可能改變了寄存器或存儲單元。軟中斷指令、單步異常是陷阱的例子。     
          中止是在系統出現嚴重情況時,通知系統的一種異常。引起中止的指令是無法確定的。產生中止時,正執行的程序不能被恢復執行。系統接收中止後,處理程序要重新建立各種系統表格,並可能重新啓動操作系統。硬件故障和系統表中出現非法值或不一致的值是中止的例子。   
軟硬中斷問題
    要搞清楚什麼是軟中斷,什麼是硬中斷,就必須瞭解軟件中斷存在的機理.
    現代的單片機應用中,往往伴隨着操作系統的應用,單片機爲了方便操作系統編程,會保留一些特權指令,方便操作系統控制整個機器,也爲了方便軟件中的一些原子操作,這些原子操作不允許中斷破壞,軟中斷指令表面上類似於函數調用,與函數調用相比,更重要的功能是使單片機進入特權運行狀態,在這個狀態下,操作系統可以做一些用戶狀態下不能使用的功能.
    像51這類沒有特權功能的單片機是不存在也沒有必要存在軟件中斷功能的.
    區別軟硬件中斷的方法很簡單,CPU的手冊會告訴你哪條指令會產生軟件中斷.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章