Linux系統調用. 複習總結

在現代操作系統中,內核提供了用戶進程與內核交互的一組接口。這些接口讓應用程序受限的訪問硬件設備,提供了創建新進程並於已有進程通信的機制,也提供了申請操作系統其他資源的能力。實際上提供這些接口主要是爲了保證系統穩定可靠,避免應用程序恣意妄爲。

1. 用戶態與內核的交互

系統調用在用戶空間進程和硬件設備之間添加了一箇中間層。該層主要作用有個:

  1. 它爲用戶空間提供了一種硬件的抽象接口。例如:在讀取文件的額時候,應用程序不用去管磁盤類型和介質,甚至不用管文件所在的文件系統到底是哪種類型。
  2. 系統調用保證了系統的穩定和安全性。作爲硬件設備和應用程序之間的中間人,內核可以基於權限、用戶類型和其他一些規則對需要進行的訪問進行裁決。例如:這樣可以避免應用程序不正確的使用設備,竊取其他進程的資源,或做出其他危害系統的事情。
  3. 爲了實現多任務和虛擬內存。每個進程運行在虛擬系統中,而在用戶空間和系統的其餘部分提供這樣一層接口,也是出於這種考慮。如果應用程序可以隨意訪問硬件而內核內核對此一無所知的話,幾乎就沒辦法實現多任務和虛擬內存,當然也不可能實現良好的穩定性和安全性。

在linux系統中,系統調用是用戶空間訪問內核的唯一手段,除異樣和陷入外,它們是內核的唯一合法入口。實際上,其他的象設備文件和/proc之類的方式,最終還是通過系統調用進行訪問的。

2. API、POSIX、和C庫 

一般情況下,應用程序通過在用戶空間實現的應用編程接口(API)而不是直接通過系統調用來編程。這點很重要,因爲應用程序使用的這種編程接口實際上並不需要和內核提供的系統調用對應。一個API定義了一組應用程序使用的編程接口。他們可以實現成以一個系統調用,也可以通過調用多個系統調用來實現,而完全不適用任何系統調用也不成問題。實際上API可以在不同的才做系統上實現,給應用程序提供完全不同的接口,而他們本身在這些系統上的實現卻可能不同。

3. 系統調用 

3.1. 系統調用號 

在Linux中,每個系統調用被賦予一個系統調用好號。這樣,通過這個獨一無二的號就可以關聯繫統調用。當用戶空間的進程執行一個系統調用的時候,這個調用號(此時存放在eax中)就用來指明到底要調用那個系統調用,進程不會提供系統調用的名稱。

系統調用號相當重要,一旦分配就不能再有任何變更,否則編譯好的應用層程序就會奔潰。此外,如果一個系統調用被刪除,它所佔用的系統調用好也不允許被回收利用,否則,以前編譯過的代碼會調用這個系統調用,但事實上調用的是另外一個系統調用。Linux有一個”未實現“系統調用sys_ni_syscall(),他除了返回-ENOSYS外不做任何其他工作,這個錯誤就是專門針對無效的系統調用而設置的。

內核中記錄了系統調用表中的所有已註冊過的系統調用列表。存儲在sys_call_table中。每一種體系結構中,都明確定義了這個表,再x86-64中,它定義於arch/i386/kernel/syscall_64.c文件中。這個表爲每一個系統調用指定了唯一的系統調用號。

3.2 系統調用處理程序

在調用系統調用的時候是通過軟中斷的方式切換到內核中的,通過引發一個異常來促使系統切換到內核態去執行異常處理程序。此時異常處理程序實際上就是系統調用處理程序。在x86系統上預定義的軟中斷是終端號128,通過int $0x80指令觸發該中斷。這條指令會觸發一個異常導致系統切換到內核態並執行128號異常處理程序,而該程序正是系統調用處理程序。這個處理程序的名字起得很貼切,叫做system_call()。

3.3 指定恰當的系統調用

因爲所有的系統調用陷入內核的方式都一樣,所以僅僅是陷入內核空間是不夠的。因爲必須把系統調用號一併傳給內核。在x86上,系統調用號是通過eax寄存器傳遞給內核的。在陷入內核之前,用戶空間就把相應的系統調用所對應的號放到eax中。這樣系統調用處理程序一旦運作就可以從eax中得到數據。其他體系結構上的實現也類似。

system_call()通過將給定的系統調用號於NR_syscalls做比較來檢查其有效性。如果它大於或者等於NR_syscalls,該函數就返回-ENOSYS。否則,執行相應的系統調用:

call *sys_call_table(,%rax,8)

由於系統調用表中的表項是以64位類型存放的,所以,內核需要將給定的系統調用乘以4,然後用得到的結果在該表中查詢其位置。

3.4. 參數傳遞

處理系統調用號外,大部分系統調用還需要一些外部的參數傳入。所以,在發生陷入的時候,應該把這些參數從用戶空間傳遞給內核。最簡單的辦法就是想傳遞系統調用號一樣,把這些參數也存放到寄存器中。在x86-32系統上,ebx、ecx、edx、esi和edi按照順序存放前五個參數。需要六個或者六個以上參數的情況不多見,此時,應該用一個單獨的寄存器存放指向所有這些參數的指在用戶空間地址的指針。

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