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,然後用所得到的結果在該表中查詢器位置。如圖所示:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章