天天看點

linux核心設計與實作:系統調用

1) 函數聲明中都有asmlinkage限定詞,用于通知編譯器僅從棧中提取該函數的參數。

2) 系統調用getXXX()在核心中被定義為sys_getXXX()。這是Linux中所有系統調用都應該遵守的命名規則。

        系統調用号:在linux中,每個系統調用都賦予一個系統調用号,通過這個獨一無二的号就可以關聯系統調用。當使用者空間的程序執行一個系統調用的時候,這個系統調用号就被用來指明到底要執行哪個系統調用;程序不會提及系統調用的名稱。系統調用号一旦配置設定就不能再有任何變更(否則編譯好的應用程式就會崩潰),如果一個系統調用被删除,它所占用的系統調用号也不允許被回收利用。Linux有一個"未使用"系統調用sys_ni_syscall(),它除了傳回-ENOSYS外不做任何其他工作,這個錯誤号就是專門針對無效的系統調用而設的。雖然很罕見,但如果有一個系統調用被删除,這個函數就要負責“填補空位”。

  核心記錄了系統調用表中所有已注冊過的系統調用的清單,存儲在sys_call_table中。它與體系結構有關,一般在entry.s中定義。這個表中為每一個有效的系統調用指定了唯一的系統調用号。

  使用者空間的程式無法直接執行核心代碼。它們不能直接調用核心空間的函數,因為核心駐留在受保護的位址空間上,應用程式應該以某種方式通知系統,告訴核心自己需要執行一個系統調用,系統系統切換到核心态,這樣核心就可以代表應用程式來執行該系統調用了。這種通知核心的機制是通過軟中斷實作的。x86系統上的軟中斷由int$0x80指令産生。這條指令會觸發一個異常導緻系統切換到核心态并執行第128号異常處理程式,而該程式正是系統調用處理程式,名字叫system_call().它與硬體體系結構緊密相關,通常在entry.s檔案中通過彙編語言編寫。

  所有的系統調用陷入核心的方式都是一樣的,是以僅僅是陷入核心空間是不夠的。是以必須把系統調用号一并傳給核心。在x86上,這個傳遞動作是通過在觸發軟中斷前把調用号裝入eax寄存器實作的。這樣系統調用處理程式一旦運作,就可以從eax中得到資料。上述所說的system_call()通過将給定的系統調用号與NR_syscalls做比較來檢查其有效性。如果它大于或者等于NR_syscalls,該函數就傳回-ENOSYS.否則,就執行相應的系統調用:

call *sys_call_table(, %eax, 4)
           

  由于系統調用表中的表項是以32位(4位元組)類型存放的,是以核心需要将給定的系統調用号乘以4,然後用所得到的結果在該表中查詢器位置。如圖所示:

linux核心設計與實作:系統調用

繼續閱讀