【Linux】系統調用過程及意義

系統調用

Linux內核中設置了一組用於實現各種系統功能的接口,稱爲系統調用。爲了方便使用操作系統,操作系統預留出了一些接口,這些接口就是系統調用函數。用戶可以通過系統調用命令在自己的應用程序中調用它們。從某種角度來看,系統調用和普通的函數調用非常相似。區別僅僅在於,系統調用由操作系統核心提供,運行於核心態;而普通的函數調用由函數庫或用戶自己提供,運行於用戶態。

系統調用號

在Linux中,每個系統調用被賦予一個系統調用號。這樣,通過這個獨一無二的號就可以關聯繫統調用。當用戶空間的進程執行一個系統調用的時候,這個系統調用號就用來指明到底是要執行哪個系統調用;進程不會提及系統調用的名稱。
系統調用號相當重要,一旦分配就不能再有任何變更,否則編譯好的應用程序就會崩潰。此外,如果一個系統調用被刪除,它所佔用的系統調用號也不允許被回收利用,否則,以前編譯過的代碼會調用這個系統調用,但事實上卻調用的是另一個系統調用。
Linux有一個“未實現”系統調用sys_ ni syscall(), 它除了返回ENOSYS外不做任何其他工作,這個錯誤號就是專門針對無效的系統調用而設的。雖然很罕見,但如果一個系統調用被刪除,或者變得不可用,這個函數就要負責“填補空缺”。

系統調用的過程

應用程序以某種方式通知系統,告訴內核自己需要執行一個系統調用,希望系統切換到內核態,這樣內核就可以代表應用程序在內核空間執行系統調用。通知內核的機制是靠軟中斷實現的:通過引發一個異常來促使系統切換到內核態去執行異常處理程序。此時的異常處理程序實際上就是系統調用處理程序。在x86系統上預定義的軟中斷是中斷號128,通過init $0x80指令觸發該中斷。這條指令會觸發一個異常導致系統切換到內核態並執行第128號異常處理程序,而該程序正是系統調用處理程序。這個處理程序名字起得很貼切,叫system_ call()。最近,x86 處理器增加了一條叫做sysenter的指令。與init中斷指令相比,這條指令提供了更快、更專業的陷入內核執行系統調用的方式。

  1. 保存上下文(用戶態執行)
  2. 用eax保存系統調用號用其他寄存器保存傳遞的參數,在x86-32系統上,ebx、 ecx、 edx、 esi 和edi按照順序存放前五個參數。(內核態執行)
  3. 系統調用必須仔細檢查它們所有的參數是否合法有效。與進程相關的函數必須檢查提供的PID是否有效。必須檢查每個參數,保證它們不但合法有效,而且正確。進程不應當讓內核去訪問那些它無權訪問的資源。然後觸發0x80中斷,首先執行system_call 函數,然後通過eax寄存器將系統調用號傳遞給內核,內核通過eax的系統調用號在系統調用表裏找到相應的系統調用函數
  4. 執行該系統調用函數。(內核態執行)
  5. 執行完畢後,轉入ret_from_sys_call 例程,從系統調用返回到用戶態。

系統調用的意義

系統調用在用戶空間進程和硬件設備之間添加了一箇中間層。該層主要作用有三個。首先,它爲用戶空間提供了一種硬件的抽象接口。舉例來說,當需要讀寫文件的時候,應用程序就可以不去管磁盤類型和介質,甚至不用去管文件所在的文件系統到底是哪種類型。第二,系統調用保證了系統的穩定和安全。作爲硬件設備和應用程序之間的中間人,內核可以基於權限、用戶類型和其他一些規則對需要進行的訪問進行裁決。舉例來說,這樣可以避免應用程序不正確地使用硬件設備,竊取其他進程的資源,或做出其他危害系統的事情。第三,每個進程都運行在虛擬系統中,而在用戶空間和系統的其餘部分提供這樣一層公共接口,也是出於這種考慮。如果應用程序可以隨意訪問硬件而內核又對此一無所知的話,幾乎就沒法實現多任務和虛擬內存,當然也不可能實現良好的穩定性和安全性。在Linux中,系統調用是用戶空間訪問內核的唯一手段;除異常和陷入外,它們是內核唯一的合法入口

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