1. 程式人生 > >【轉】中斷的作用

【轉】中斷的作用

頁面 發生 call 由於 pan con sys_call 都是 handle

來源:CSDN

鏈接:http://blog.csdn.net/keyue123/article/details/16959111

所有的事物都是依靠中斷來解決問題的。計算機更是如此,依靠時鐘發生器,人為的設置沒幾個時鐘周期做一個任務,不管是否做完,一旦規定的時間到了,那麽就要強制“中斷”,以作下一個任務……就這樣,直道所有的任務都作過了(但不一定都做完畢),再接著做第一個沒有做完的任務,就這樣走而復始循環工作。完成所謂的“多任務”。
要不然,一個cpu,如果即能一邊打字,一邊看到屏幕呢?這就是一個cpu核心,不斷地一會檢測鍵盤,一會檢測屏幕……
還有就是軟中斷,具體詳細的細節,可以參考微機原理。 中斷系統
中斷裝置和中斷處理程序統稱為中斷系統

中斷系統是計算機的重要組成部分。實時控制、故障自動處理、計算機與外圍設備間的數據傳送往往采用中斷系統。中斷系統的應用大大提高了計算機效率。

不同的計算機其硬件結構和軟件指令是不完全相同的,因此,中斷系統也是不相同的。計算機的中斷系統能夠加強CPU對多任務事件的處理能力。中斷機制是現代計算機系統中的基礎設施之一,它在系統中起著通信網絡作用,以協調系統對各種外部事件的響應和處理。中斷是實現多道程序設計的必要條件。中斷是CPU對系統發生的某個事件作出的一種反應。引起中斷的事件稱為中斷源。中斷源向CPU提出處理的請求稱為中斷請求。發生中斷時被打斷程序的暫停點成為斷點
。CPU暫停現行程序而轉為響應中斷請求的過程稱為中斷響應。處理中斷源的程序稱為中斷處理程序。CPU執行有關的中斷處理程序稱為中斷處理。而返回斷點的過程稱為中斷返回。中斷的實現實行軟件和硬件綜合完成,硬件部分叫做硬件裝置,軟件部分成為軟件處理程序。

中斷系統的功能

1)實現中斷響應和中斷返回

當CPU收到中斷請求後,能根據具體情況決定是否響應中斷,如果CPU沒有更急、更重要的工作,則在執行完當前指令後響應這一中斷請求。CPU中斷響應過程如下:首先,將斷點處的PC值(即下一條應執行指令的地址)推入堆棧保留下來,這稱為保護斷點,由硬件自動執行。然後,將有關的寄存器內容和標誌位狀態推入堆棧保留下來,這稱為保護現場,由用戶自己編程完成。保護斷點和現場後即可執行中斷服務程序,執行完畢,CPU由中斷服務程序返回主程序,中斷返回過程如下:首先恢復原保留寄存器的內容和標誌位的狀態,這稱為恢復現場,由用戶編程完成。然後,再加返回指令RETI,RETI指令的功能是恢復PC值,使CPU返回斷點,這稱為恢復斷點。恢復現場和斷點後,CPU將繼續執行原主程序,中斷響應過程到此為止。

2)實現優先權排隊

通常,系統中有多個中斷源,當有多個中斷源同時發出中斷請求時,要求計算機能確定哪個中斷更緊迫,以便首先響應。為此,計算機給每個中斷源規定了優先級別,稱為優先權。這樣,當多個中斷源同時發出中斷請求時,優先權高的中斷能先被響應,只有優先權高的中斷處理結束後才能響應優先權低的中斷。計算機按中斷源優先權高低逐次響應的過程稱優先權排隊,這個過程可通過硬件電路來實現,亦可通過軟件查詢來實現。

3)實現中斷嵌套
當CPU響應某一中斷時,若有優先權高的中斷源發出中斷請求,則CPU能中斷正在進行的中斷服務程序,並保留這個程序的斷點(類似於子程序嵌套),響應高級中斷,高級中斷處理結束以後,再繼續進行被中斷的中斷服務程序,這個過程稱為中斷嵌套。如果發出新的中斷請求的中斷源的優先權級別與正在處理的中斷源同級或更低時,CPU不會響應這個中斷請求,直至正在處理的中斷服務程序執行完以後才能去處理新的中斷請求。
中斷、異常和系統調用

所謂中斷是指CPU對系統發生的某個事件做出的一種反應,CPU暫停正在執行的程序,保留現場後自動地轉去執行相應的處理程序,處理完該事件後再返回斷點繼續執行被“打斷”的程序。

中斷可分為三類,第一類是由CPU外部引起的,稱作中斷,如I/O中斷、時鐘中斷、控制臺中斷等。第二類是來自CPU的內部事件或程序執行中的事件引起的過程,稱作異常,如由於CPU本身故障(電源電壓低於105V或頻率在47~63Hz之外)、程序故障(非法操作碼、地址越界、浮點溢出等)等引起的過程。

第三類由於在程序中使用了請求系統服務的系統調用而引發的過程,稱作“陷入”(trap,或者陷阱)。前兩類通常都稱作中斷,它們的產生往往是無意、被動的,而陷入是有意和主動的。

1.中斷處理

中斷處理一般分為中斷響應和中斷處理兩個步驟。中斷響應由硬件實施,中斷處理主要由軟件實施。

(1)中斷響應

對中斷請求的整個處理過程是由硬件和軟件結合起來而形成的一套中斷機構實施的。發生中斷時,CPU暫停執行當前的程序,而轉去處理中斷。這個由硬件對中斷請求作出反應的過程,稱為中斷響應。一般說來,中斷響應順序執行下述三步動作:

◆中止當前程序的執行;

◆保存原程序的斷點信息(主要是程序計數器PC和程序狀態寄存器PS的內容);

◆從中斷控制器取出中斷向量,轉到相應的處理程序。

通常CPU在執行完一條指令後,立即檢查有無中斷請求,如果有,則立即做出響應。

當發生中斷時,系統作出響應,不管它們是來自硬件(如來自時鐘或者外部設備)、程序性中斷(執行指令導致“軟件中斷”—SoftwareInterrupts),或者來自意外事件(如訪問頁面不在內存)。

如果當前CPU的執行優先級低於中斷的優先級,那麽它就中止對當前程序下條指令的執行,接受該中斷,並提升處理機的執行級別(一般與中斷優先級相同),以便在CPU處理當前中斷時,能屏蔽其它同級的或低級的中斷,然後保存斷點現場信息,通過取得的中斷向量轉到相應的中斷處理程序的入口。

(2)中斷處理

CPU從中斷控制器取得中斷向量,然後根據具體的中斷向量從中斷向量表IDT中找到相應的表項,該表項應是一個中斷門。於是,CPU就根據中斷門的設置而到達了該通道的總服務程序的入口。

核心對中斷處理的順序主要由以下動作完成:

◆保存正在運行進程的各寄存器的內容,把它們放入核心棧的新幀面中。

◆確定“中斷源”或核查中斷發生,識別中斷的類型(如時鐘中斷或盤中斷)和中斷的設備號(如哪個磁盤引起的中斷)。系統接到中斷後,就從機器那裏得到一個中斷號,它是檢索中斷向量表的位移。中斷向量因機器而異,但通常都包括相應中斷處理程序入口地址和中斷處理時處理機的狀態字。

◆核心調用中斷處理程序,對中斷進行處理。

◆中斷處理完成並返回。中斷處理程序執行完以後,核心便執行與機器相關的特定指令序列,恢復中斷時寄存器內容和執行核心棧退棧,進程回到用戶態。如果設置了重調度標誌,則在本進程返回到用戶態時做進程調度。

2.系統調用

在Unix/Linux系統中,系統調用像普通C函數調用那樣出現在C程序中。但是一般的函數調用序列並不能把進程的狀態從用戶態變為核心態,而系統調用卻可以做到。

C語言編譯程序利用一個預先確定的函數庫(一般稱為C庫),其中有各系統調用的名字。C庫中的函數都專門使用一條指令,把進程的運行狀態改為核心態。Linux的系統調用是通過中斷指令“INT0x80”實現的。

每個系統調用都有惟一的號碼,稱作系統調用號。所有的系統調用都集中在系統調用入口表中統一管理。

系統調用入口表是一個函數指針數組,以系統調用號為下標在該數組中找到相應的函數指針,進而就能確定用戶使用的是哪一個系統調用。不同系統中系統調用的個數是不同的,目前Linux系統中共定義了221個系統調用。

另外,系統調用表中還留有一些余項,可供用戶自行添加。

當CPU執行到中斷指令“INT0x80”時,硬件就做出一系列響應,其動作與上述的中斷響應相同。CPU穿過陷阱門,從用戶空間進入系統空間。相應地,進程的上下文從用戶堆棧切換到系統堆棧。

接著運行內核函數system_call()。首先,進一步保存各寄存器的內容;接著調用syscall_trace(),以系統調用號為下標檢索系統調用入口表sys_call_table,從中找到相應的函數;然後轉去執行該函數,完成具體的服務。

執行完服務程序,核心檢查是否發生錯誤,並作相應處理。如果本進程收到信號,則對信號作相應處理。最後進程從系統空間返回到用戶空間。

上面兩講簡要介紹了Linux內核的主要數據結構和相應的算法。Linux內核包含了豐富的內容,這裏僅是其中的一點點,以求起到“拋磚引玉”的作用。





信號的中斷與系統調用的重起



#include <signal.h> int sigaction(ints signo, const structsigaction *act, struct sigaction *oact) ; struct sigaction { void(*sa_handler)(); /* addr of signal handler, or SIG_IGN, or SIG_DFL*/ sigset_t sa_mask; /* additional signals to block */ intsa_flags; /* signal options*/ } ; 當更改信號動作時,如果sa_handler指向一個信號捕捉函數(不是常數SIG_IGN或SIG_DFL),則sa_mask字段說明了一個信號集,在調用信號捕捉函數之前,該信號集要加到進程的信號屏蔽字中。僅當從信號捕捉函數返回時再將進程的信號屏蔽字恢復為原先值。這樣,在調用信號處理程序時就能阻塞某些信號。在信號處理程序被調用時,系統建立的新信號屏蔽字會自動包括正被遞送的信號。因此保證了在處理一個給定的信號時,如果這種信號再次發生,那麽它會被阻塞到對前一個信號的處理結束為止。A.可自動重起的signal()的實現: #include <signal.h> #typpdef voidSigfunc(int signo); Sigfunc *signal(int signo, Sigfunc *func){ struct sigaction act, oact; act.sa_handler = func; sigemptyset(act.sa_mask); act.sa_flags = 0; if (signo == SIGALRM){ #ifdef SA_INTTERRUPT //SUNOS act.flags |= SA_INTTERRUPT; #endif } else // for other signal {#ifdef SA_RESTART //SVR, 4.3+BSD act.flag|= SA_RESTART; #endif } if (sigaction(signo, &act, &oac)< 0) return (SIG_ERR); return (oact.sa_handler); } 註:在if語句中,我們檢查是否為SIGALRM信號,如果是,且系統定義了SA_INTERRUPT(SUNOS),即為SUNOS,該系統默認的系統調用是自動重起的,我們阻止該信號中斷的系統調用重起,因為我們要用該信號中斷I/O操作,實現定時的功能.接著的else語句中的信號為SIGALRM之外的其他信號,且系統定義了SA_RESTART,即為SVR4或4.3+BSD類系統,該類系統中默認的系統調用是不可重起的,所以應該加上SA_RESTART標誌,使由這些信號中斷的系統調用自動重起.B.不可重起的signal_intr()實現: Sigfunc *signal_intr(int signo,Sigfunc *func) {
struct sigaction act, oact;

act.sa_handler = func;
sigemptyset(act.sa_mask);
act.sa_flags = 0;

#ifdef SA_INTTERRUPT //SUNOS
act.flags |= SA_INTTERRUPT;
#endif
if (sigaction(signo, &act, &oac) < 0)
return (SIG_ERR);

return (oact.sa_handler);
}
註:只有SUNOS為自動重起的,其他為不自動重起的,所以只要將SUNOS標誌為非自動重起即可.如上.

【轉】中斷的作用