系統(tǒng)調(diào)用是受控的內(nèi)核入口,借助于這一機制,進程可以請求內(nèi)核以自己的名義去執(zhí)行某些動作。以應(yīng)用程序編程接口(API)的形式,內(nèi)核有提供一系列服務(wù)供程序訪問。這些包括創(chuàng)建進程、執(zhí)行I/O,以及為進程間通信創(chuàng)建管道等。
在深入系統(tǒng)調(diào)用的運作方式之前,務(wù)必關(guān)注以下幾點:
- 系統(tǒng)調(diào)用將處理器從用戶態(tài)切換到內(nèi)核態(tài),以便CPU訪問受到保護的內(nèi)核內(nèi)存。
- 系統(tǒng)調(diào)用的組成是固定的,每個系統(tǒng)調(diào)用都由一個唯一的數(shù)字來表示。
- 每個系統(tǒng)調(diào)用可輔之以一套參數(shù),對用戶空間(亦即進程的虛擬地址空間)與內(nèi)核空間之間(相互)傳遞的信息加以規(guī)范。
按事件發(fā)生的順序,詳細步驟如下:
- 應(yīng)用程序通過調(diào)用C語言函數(shù)庫中的外殼(wrapper)函數(shù),來發(fā)起系統(tǒng)調(diào)用。
- 對系統(tǒng)調(diào)用中斷處理歷程來說,外殼函數(shù)必須保證所有的系統(tǒng)調(diào)用參數(shù)可用。通過堆棧,這些參數(shù)傳入外殼函數(shù),但內(nèi)核卻希望將這些參數(shù)置入特定寄存器。因此,外殼函數(shù)會將上述參數(shù)復(fù)制到寄存器。
- 由于所有系統(tǒng)調(diào)用進入內(nèi)核的方式相同,內(nèi)黑需要設(shè)法區(qū)分每個系統(tǒng)調(diào)用。為此,外殼函數(shù)會將系統(tǒng)調(diào)用編號復(fù)制到一個特殊的CPU寄存器(%eax)中。
- 外殼函數(shù)執(zhí)行一條中斷機器指令(int 0x80),引發(fā)處理器從用戶態(tài)切換到內(nèi)核態(tài),并執(zhí)行系統(tǒng)中斷0x80的中斷矢量所指代的代碼。
- 為響應(yīng)中斷0x80,內(nèi)核會調(diào)用system_call()例程來處理這次中斷,具體如下:
- 在內(nèi)核棧中保存寄存器值。
- 審核系統(tǒng)調(diào)用編號的有效性。
- 以系統(tǒng)調(diào)用編號對存放所有調(diào)用服務(wù)例程的列表(內(nèi)核變量sys_call_table)進行索引,發(fā)現(xiàn)并調(diào)用相應(yīng)的系統(tǒng)調(diào)用服務(wù)例程。若系統(tǒng)調(diào)用服務(wù)例程帶有參數(shù),那么將首先檢查參數(shù)的有效性。隨后服務(wù)例程會執(zhí)行必要的任務(wù),這可能涉及對特定參數(shù)中指定地址處的值進行修改,以及在用戶內(nèi)存和內(nèi)核內(nèi)存間傳遞數(shù)據(jù)。最后,該服務(wù)例程會將結(jié)果狀態(tài)返回給system_call()例程。
- 從內(nèi)核棧中恢復(fù)各寄存器值,并將系統(tǒng)調(diào)用返回值置于棧中。
- 返回至外殼函數(shù),同時將處理器切換會用戶態(tài)。
- 若系統(tǒng)調(diào)用服務(wù)例程的返回值表名調(diào)用有誤,外殼函數(shù)會使用該值來設(shè)置全局變量errno。然后,外殼函數(shù)會返回到調(diào)用程序,并同時返回一個整型值,以表明系統(tǒng)調(diào)用是否成功。