版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。
最近學習Linux作業系統,關于中斷系統調用和程序的級别總是感覺有些模糊的地方,特在此做個小結,整理下思路。
所謂的中斷就是在計算機執行程式的過程中,由于出現了某些特殊事情,使得CPU暫停對程式的執行,轉而去執行處理這一事件的程式。等這些特殊事情處理完之後再回去執行之前的程式。中斷一般分為三類:1、由計算機硬體異常或故障引起的中斷,稱為内部異常中斷;2、由程式中執行了引起中斷的指令而造成的中斷,稱為軟中斷(這也是和我們将要說明的系統調用相關的中斷);3、由外部裝置請求引起的中斷,稱為外部中斷。簡單來說,對中斷的了解就是對一些特殊事情的處理。
與中斷緊密相連的一個概念就是中斷處理程式了。當中斷發生的時候,系統需要去對中斷進行處理,對這些中斷的處理是由作業系統核心中的特定函數進行的,這些進行中斷的特定的函數就是我們所說的中斷處理程式了。
另一個與中斷緊密相連的概念就是中斷的優先級。中斷的優先級說明的是當一個中斷正在被處理的時候,處理器能接受的中斷的級别。中斷的優先級也表明了中斷需要被處理的緊急程度。每個中斷都有一個對應的優先級,當處理器在處理某一中斷的時候,隻有比這個中斷優先級高的中斷可以被處理器接受并且被處理。優先級比這個目前正在被處理的中斷優先級要低的中斷将會被忽略。
典型的中斷級如下所示

當發生軟體中斷時,其他所有的中斷都可能發生并被處理;但當發生磁盤中斷時,就隻有時鐘中斷和機器錯誤中斷能被處理了。
在講系統調用之前,先說下程序的執行在系統上的兩個級别:使用者級和核心級,也稱為使用者态和系統态(user mode and kernel mode)。程式的執行一般是在使用者态下執行的,但當程式需要使用作業系統提供的服務時,比如說打開某一裝置、建立檔案、讀寫檔案等,就需要向作業系統發出調用服務的請求,這就是系統調用。Linux系統有專門的函數庫來提供這些請求作業系統服務的入口,這個函數庫中包含了作業系統說提供的對外服務的接口。當程序發出系統調用之後,它所處的運作狀态就會由使用者态變成核心态。但這個時候,程序本身其實并沒有做什麼事情,這個時候是由核心在做相應的操作,去完成程序所提出的這些請求。
系統調用和中斷的關系就在于,當程序發出系統調用申請的時候,會産生一個軟體中斷。産生這個軟體中斷以後,系統會去對這個軟中斷進行處理,這個時候程序就處于核心态了。
那麼使用者态和核心态之間的差別是什麼呢?(以下差別摘至《UNIX作業系統設計》)
1、使用者态的程序能存取它們自己的指令和資料,但不能存取核心指令和資料(或其他程序的指令和資料)。然而,核心态下的程序能夠存取核心和使用者位址
2、某些機器指令是特權指令,在使用者态下執行特權指令會引起錯誤
對此要了解的一個是,在系統中核心并不是作為一個與使用者程序平行的估計的程序的集合,核心是為使用者程序運作的。
如何去了解上面所說的差別,特别是差別1呢?真正了解這點,需要對程序在記憶體中的表示有個大緻的了解。
每個程式需要被裝入(全部或部分)裝入記憶體後才能開始運作,在32位機器中,每個程序都有4G的虛拟位址空間。但是對這4G的空間并不是全部都可以被程序使用的,在Linux中,對這4G的空間的大緻劃分如下
是以,從原則上來說,在程序中使用者能使用的虛拟位址空間是隻有3G的。正常情況下,使用者程式在使用者态運作的時候,隻能通路在這3G範圍内的位址(當然也不是所有位址都能通路)。當程序由于系統調用而進入核心态時,這時系統核心會執行相應的操作,它能通路自己1G的位址空間,同時也能通路3G的使用者位址空間。而使用者程序的指令的資料是存在與那3G的位址空間中的。當然還有程序的棧等部分。
細分來說的話,一個程序在記憶體中一般包含以下部分,資料段、指令段、運作時堆、棧等。示意圖如下
核心自己的棧這在最上層的1G的位址空間内,這是隻能由核心通路的部分。
在說程序排程之前,首先整理下程序可能的各種狀态。首先我們知道程序的運作狀态是分為核心态和使用者态。其他的程序狀态包括如下
程序未被執行,但出于就緒狀态,隻要核心排程它,即可執行
程序正在睡眠中并且存在主存中
程序處于就緒狀态,但處在二級存儲器中
程序在睡眠中,且在二級存儲器中
程序執行完核心态的操作,正要傳回使用者态時,核心做了程序排程,切換了上下文
程序剛被建立
程序調用了exit,處于僵死狀态
程序之間的狀态轉換示意圖如下,箭頭指明了轉換的方向
程序的各種狀态的轉換比較複雜,這裡主要關注程序的兩個運作狀态、睡眠以及從就緒到運作的轉換
從示意圖中可以看出,當發生中斷或者系統調用時,程序由使用者态轉成核心态。但程序在核心态運作時,是不能被搶占的,是以隻有當程序由核心态進入睡眠狀态時,或者程序處于使用者态時,核心才允許做程序排程,切換上下文。而處于就緒狀态的程序當被核心排程開始運作的時候,首先是進入核心态的。
這就涉及到另一個問題,中斷是在任何時刻都能發生的,并且對中斷的處理也可能影響核心資料的一緻性。那麼,但程序在核心态運作時,對于發生中斷的情況又如何保證核心資料的一緻性呢?解決的方法大緻分為兩類,一種是簡單地在核心态時,禁止所有的中斷,但這樣會降低對中斷的響應速度;另一種方法是設立臨界區,找出操作語句中可能會導緻核心資料不一緻的地方,然後将這部分設為臨界區。但CPU執行臨界區代碼時,把CPU的執行級别提高,這樣就可以屏蔽掉很多的中斷,進而保證資料的一緻性了。一般,為了保證系統的性能,臨界區都很小,并且不會經常出現。
本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sky-heaven/p/5746732.html,如需轉載請自行聯系原作者