linux系統程式設計之訊號(一):中斷與訊號

mickole發表於2013-07-14

一,什麼是中斷?

1.中斷的基本概念

中斷是指計算機在執行期間,系統內發生任何非尋常的或非預期的急需處理事件,使得CPU暫時中斷當前正在執行的程式而轉去執行相應的事件處理程式,待處理完畢後又返回原來被中斷處繼續執行或排程新的程式執行的過程。引起中斷髮生的事件被稱為中斷源。中斷源向CPU發出的請求中斷處理訊號稱為中斷請求,而CPU收到中斷請求後轉到相應的事件處理程式稱為中斷響應。

在有些情況下,儘管產生了中斷源和發出了中斷請求,但CPU內部的處理器狀態字PSW的中斷允許位已被清除,從而不允許CPU響應中斷。這種情況稱為禁止中斷。CPU禁止中斷後只有等到PSW的中斷允許位被重新設定後才能接收中斷。禁止中斷也稱為關中斷,PSW的中斷允許位的設定也被稱為開中斷。開中斷和關中斷是為了保證某段程式執行的原子性。

還有一個比較常用的概念是中斷遮蔽。中斷遮蔽是指在中斷請求產生之後,系統有選擇地封鎖一部分中斷而允許另一部分中斷仍能得到響應。不過,有些中斷請求是不能遮蔽甚至不能禁止的,也就是說,這些中斷具有最高優先順序,只要這些中斷請求一旦提出,CPU必須立即響應。例如,電源掉電事件所引起的中斷就是不可禁止和不可遮蔽的。

2.中斷的分類與優先順序

根據系統對中斷處理的需要,作業系統一般對中斷進行分類並對不同的中斷賦予不同的處理優先順序,以便在不同的中斷同時發生時,按輕重緩急進行處理。

根據中斷源產生的條件,可把中斷分為外中斷和內中斷。外中斷是指來自處理器和記憶體外部的中斷,包括I/0裝置發出的I/O中斷、外部訊號中斷(例如使用者鍵人ESC鍵)。各種定時器引起的時鐘中斷以及除錯程式中設定的斷點等引起的除錯中斷等。外中斷在狹義上一般被稱為中斷。

內中斷主要指在處理器和記憶體內部產生的中斷。內中斷一般稱為陷阱(trap)或異常。它包括程式運算引起的各種錯誤,如地址非法、校驗錯、頁面失效、存取訪問控制錯、算術操作溢位、資料格式非法、除數為零、非法指令、使用者程式執行特權指令、分時系統中的時間片中斷以及從使用者態到核心態的切換等都是陷阱的例子。

為了按中斷源的輕重緩急處理響應中斷,作業系統為不同的中斷賦予不同的優先順序。例如在UNIX系統中,外中斷和陷阱的優先順序共分為8級。為了禁止中斷或遮蔽中斷,CPU的處理器狀態字PSW中也設有相應的優先順序。如果中斷源的優先順序高於PSW的優先順序,則CPU響應該中斷源的請求;反之,CPU遮蔽該中斷源的中斷請求。

各中斷源的優先順序在系統設計時給定,在系統執行時是固定的。而處理器的優先順序則根據執行情況由系統程式動態設定。

除了在優先順序的設定方面有區別之外,中斷和陷阱還有如下主要區別:

陷阱通常由處理器正在執行的現行指令引起,而中斷則是由與現行指令無關的中斷源引起的。陷阱處理程式提供的服務為當前程式所用,而中斷處理程式提供的服務則不是為了當前程式的。

CPU執行完一條指令之後,下一條指令開始之前響應中斷,而在一條指令執行中也可以響應陷阱。例如執行指令非法時,儘管被執行的非法指令不能執行結束,但CPU仍可對其進行處理。

3.軟中斷

軟中斷的概念主要來源於UNIX系統。軟中斷是對應於硬中斷而言的。通過硬體產生相應的中斷請求,稱為硬中斷。而軟中斷則不然,它是在通訊程式之間通過模擬硬中斷而實現的一種通訊方式。中斷源發出軟中斷訊號後,CPU或者接收程式在“適當的時機”進行中斷處理或者完成軟中斷訊號所對應的功能。這裡“適當的時機”,表示接收軟中斷訊號的程式須等到該接收程式得到處理器之後才能進行。如果該接收程式是佔據處理器的,那麼,該接收程式在接收到軟中斷訊號後將立即轉去執行該軟中斷訊號所對應的功能。

4.中斷處理過程

一旦CPU響應中斷,轉人中斷處理程式,系統就開始進行中斷處理。下面對中斷處理過程進行詳細說明:

1)CPU檢查響應中斷的條件是否滿足。CPU響應中斷的條件是:有來自於中斷源的中斷請求、CPU允許中斷。如果中斷響應條件不滿足,則中斷處理無法進行。

2)如果CPU響應中斷,則CPU關中斷,使其進入不可再次響應中斷的狀態。

3)儲存被中斷程式現場。為了在中斷處理結束後能使程式正確地返回到中斷點,系統必須儲存當前處理器狀態字PSW和程式計數器PC等的值。這些值一般儲存在特定堆疊或硬體暫存器中。

4)分析中斷原因,呼叫中斷處理子程式。在多箇中斷請求同時發生時,處理優先順序最高的中斷源發出的中斷請求。在系統中,為了處理上的方便,通常都是針對不同的中斷源編制有不同的中斷處理子程式(陷阱處理子程式)。這些子程式的人口地址(或陷阱指令的人口地址)存放在記憶體的特定單元中。再者,不同的中斷源也對應著不同的處理器狀態字PSW。這些不同的PSW被放在相應的記憶體單元中,與中斷處理子程式人口地址一起構成中斷向量。顯然,根據中斷或陷阱的種類,系統可由中斷向量表迅速地找到該中斷響應的優先順序、中斷處理子程式(或陷阱指令)的入口地址和對應的PSW。

5)執行中斷處理子程式。對陷阱來說,在有些系統中則是通過陷阱指令向當前執行程式發出軟中斷訊號後呼叫對應的處理子程式執行。

6)退出中斷,恢復被中斷程式的現場或排程新程式佔據處理器。

7)開中斷,CPU繼續執行。

5.裝置管理程式與中斷方式

處理器的高速和輸入輸出裝置低速之間的矛盾,是裝置管理要解決的一個重要問題。為了提高整體效率,減少在程式直接控制方式中的CPU等待時間以及提高系統的並行工作效率,採用中斷方式來控制輸入輸出裝置和記憶體與CPU之間的資料傳送,是很有必要的。

在硬體結構上,這種方式要求CPU與輸入輸出裝置(或控制器)之間有相應的中斷請求線,而且在輸入輸出裝置控制器的控制狀態暫存器上有相應的中斷允許位。

二,什麼是訊號?

1、訊號及訊號來源

訊號本質

訊號是在軟體層次上對中斷機制的一種模擬,在原理上,一個程式收到一個訊號與處理器收到一箇中斷請求可以說是一樣的。訊號是非同步的,一個程式不必通過任何操作來等待訊號的到達,事實上,程式也不知道訊號到底什麼時候到達。

訊號是程式間通訊機制中唯一的非同步通訊機制,可以看作是非同步通知,通知接收訊號的程式有哪些事情發生了。訊號機制經過POSIX實時擴充套件後,功能更加強大,除了基本通知功能外,還可以傳遞附加資訊。

訊號來源

訊號事件的發生有兩個來源:硬體來源(比如我們按下了鍵盤或者其它硬體故障);軟體來源,最常用傳送訊號的系統函式是kill, raise, alarm和setitimer以及sigqueue函式,軟體來源還包括一些非法運算等操作。

2、訊號的種類

可以從兩個不同的分類角度對訊號進行分類:(1)可靠性方面:可靠訊號與不可靠訊號;(2)與時間的關係上:實時訊號與非實時訊號。在《Linux環境程式間通訊(一):管道及有名管道》的附1中列出了系統所支援的所有訊號。

(一)、可靠訊號與不可靠訊號

"不可靠訊號"

Linux訊號機制基本上是從Unix系統中繼承過來的。早期Unix系統中的訊號機制比較簡單和原始,後來在實踐中暴露出一些問題,因此,把那些建立在早期機制上的訊號叫做"不可靠訊號",訊號值小於SIGRTMIN(Red hat 7.2中,SIGRTMIN=32,SIGRTMAX=63)的訊號都是不可靠訊號。這就是"不可靠訊號"的來源。它的主要問題是:

  • 程式每次處理訊號後,就將對訊號的響應設定為預設動作。在某些情況下,將導致對訊號的錯誤處理;因此,使用者如果不希望這樣的操作,那麼就要在訊號處理函式結尾再一次呼叫signal(),重新安裝該訊號。
  • 訊號可能丟失,後面將對此詳細闡述。
    因此,早期unix下的不可靠訊號主要指的是程式可能對訊號做出錯誤的反應以及訊號可能丟失。

Linux支援不可靠訊號,但是對不可靠訊號機制做了改進:在呼叫完訊號處理函式後,不必重新呼叫該訊號的安裝函式(訊號安裝函式是在可靠機制上的實現)。因此,Linux下的不可靠訊號問題主要指的是訊號可能丟失。

"可靠訊號"

隨著時間的發展,實踐證明了有必要對訊號的原始機制加以改進和擴充。所以,後來出現的各種Unix版本分別在這方面進行了研究,力圖實現"可靠訊號"。由於原來定義的訊號已有許多應用,不好再做改動,最終只好又新增加了一些訊號,並在一開始就把它們定義為可靠訊號,這些訊號支援排隊,不會丟失。同時,訊號的傳送和安裝也出現了新版本:訊號傳送函式sigqueue()及訊號安裝函式sigaction()。POSIX.4對可靠訊號機制做了標準化。但是,POSIX只對可靠訊號機制應具有的功能以及訊號機制的對外介面做了標準化,對訊號機制的實現沒有作具體的規定。

訊號值位於SIGRTMIN和SIGRTMAX之間的訊號都是可靠訊號,可靠訊號克服了訊號可能丟失的問題。Linux在支援新版本的訊號安裝函式sigation()以及訊號傳送函式sigqueue()的同時,仍然支援早期的signal()訊號安裝函式,支援訊號傳送函式kill()。

注:不要有這樣的誤解:由sigqueue()傳送、sigaction安裝的訊號就是可靠的。事實上,可靠訊號是指後來新增的新訊號(訊號值位於SIGRTMIN及SIGRTMAX之間);不可靠訊號是訊號值小於SIGRTMIN的訊號。訊號的可靠與不可靠只與訊號值有關,與訊號的傳送及安裝函式無關。目前linux中的signal()是通過sigation()函式實現的,因此,即使通過signal()安裝的訊號,在訊號處理函式的結尾也不必再呼叫一次訊號安裝函式。同時,由signal()安裝的實時訊號支援排隊,同樣不會丟失。

對於目前linux的兩個訊號安裝函式:signal()及sigaction()來說,它們都不能把SIGRTMIN以前的訊號變成可靠訊號(都不支援排隊,仍有可能丟失,仍然是不可靠訊號),而且對SIGRTMIN以後的訊號都支援排隊。這兩個函式的最大區別在於,經過sigaction安裝的訊號都能傳遞資訊給訊號處理函式(對所有訊號這一點都成立),而經過signal安裝的訊號卻不能向訊號處理函式傳遞資訊。對於訊號傳送函式來說也是一樣的。

(二)、實時訊號與非實時訊號

早期Unix系統只定義了32種訊號,Ret hat7.2支援64種訊號,編號0-63(SIGRTMIN=31,SIGRTMAX=63),將來可能進一步增加,這需要得到核心的支援。前32種訊號已經有了預定義值,每個訊號有了確定的用途及含義,並且每種訊號都有各自的預設動作。如按鍵盤的CTRL ^C時,會產生SIGINT訊號,對該訊號的預設反應就是程式終止。後32個訊號表示實時訊號,等同於前面闡述的可靠訊號。這保證了傳送的多個實時訊號都被接收。實時訊號是POSIX標準的一部分,可用於應用程式。

非實時訊號都不支援排隊,都是不可靠訊號;實時訊號都支援排隊,都是可靠訊號。

(三),訊號名稱

檢視linux所支援的訊號可用:kill –l

共64種:

QQ截圖20130714104059

QQ截圖20130714104217

QQ截圖20130714104231

3、程式對訊號的響應

程式可以通過三種方式來響應一個訊號:(1)忽略訊號,即對訊號不做任何處理,其中,有兩個訊號不能忽略:SIGKILL及SIGSTOP;(2)捕捉訊號。定義訊號處理函式,當訊號發生時,執行相應的處理函式;(3)執行預設操作,Linux對每種訊號都規定了預設操作,詳細情況請參考[2]以及其它資料。注意,程式對實時訊號的預設反應是程式終止。

Linux究竟採用上述三種方式的哪一個來響應訊號,取決於傳遞給相應API函式的引數。

注:本文參考:http://blog.csdn.net/lmh12506/article/details/6681663

 http://blog.csdn.net/johnny710vip/article/details/6990514

相關文章