linux下系統調用的過程

系統調用:

系統調用是內核的入口 ,藉助這一機制,進程可以請求內核以自己的名義去執行某些動作。以應用程序編程接口(API)的形式,內核提供一系列API供應用程序調用

在深入系統調用的運作方式之前需得理解下面幾點:

  • 系統調用將處理器從用戶狀態切換到內核狀態,以便cpu訪問受到保護的系統內核
  • 系統調用的組成是固定的,每個系統調用都有一個唯一的數字標識符,程序通過名稱來標識系統調用
  • 每個系統調用可以輔之以一套參數,對用戶空間(亦即進程的虛擬內存空間)與內核空間之間傳遞信息加以規範

從編程的角度講,系統調用和調用c語言的函數很像,然而,在執行系統調用時,會比c語言的函數調用複雜很多,下面是系統調用的詳細過程:

  1. 應用程序通過調用c語言函數庫中的外殼函數(wrapper)來發起系統調用。
  2. 對系統調用中斷來處理例程來講,外殼函數必須保證所有的系統調用的參數可用。通過堆棧這些參數傳入外殼函數後,外殼函數會將這些參數複製到寄存器。
  3. 所有系統調用進入內核的方式都相同,所以內核需要區分每個系統調用,爲此,外殼函數會把系統調用的編號複製到一個特殊的cpu(%eax)
  4. 外殼函數調用系統中斷指令(int 0x80),引發處理器從用戶態切換到內核態,並執行系統中斷的中斷矢量所指向的代碼。

較新的x86_32硬件平臺實現了sysenter指令,比傳統的int 0x80進入內核的速度更快,2.6內核和glibc2.3.2以後的版本都支持sysenter指令

  1. 爲了響應中斷0x80,內核會調用system_call()例程,來處理這次中斷。

1、 在內核棧中保存寄存器的值 在內核棧中保存寄存器的值
2、審覈系統調用編號的有效性。
3、以系統調用編號對存放所有調用服務例程的列表(內核變量sys_call_table)進行索引,發現並調用相應編號的系統例程。若系統調用例程帶有參數,那麼首先檢查參數的有效性,例如,會檢查地址指向用戶空間的內存的位置是否有效。隨後該服務例程會執行必要的任務,這可能涉及對特定參數中指定地址處的值的修改,以及在用戶內存和內核內存中傳遞數據,最後,該服務例程會將結果返回給system_call()例程。

  1. 若系統調用例程的返回值表明調用有誤,外殼函數會將該值用來設置全局變量errno,然後外殼函數會返回到調用函數,並同時返回一個整數0或者-1,0表示成功,-1表示失敗。通過查看全局變量erron來獲取錯誤信息。

下面是exec函數的系統調用的流程圖:

在這裏插入圖片描述

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