Linux系统调用FAQ
1. Linux系統(tǒng)調(diào)用的作用?
系統(tǒng)調(diào)用是操作系統(tǒng)為用戶態(tài)運行的進程與系統(tǒng)內(nèi)核、硬件設(shè)備(如CPU、磁盤、打印機等)進行交互提供的一組接口,在應(yīng)用程序和硬件之間設(shè)置一個額外層的優(yōu)點包括:
1.???????? 用戶編程更加簡單,不必學習硬件設(shè)備的低級編程特性;
2.???????? 提高了系統(tǒng)的安全性,內(nèi)核在試圖滿足某個請求前在接口級可以檢查請求正確性。
3.???????? 這組接口使得程序具有可移植性,只要內(nèi)核所提供的接口相同,使用這些接口的?? ?????程序即可正確的編譯和執(zhí)行。
2. POSIX API與系統(tǒng)調(diào)用的關(guān)系?
1.???????? API是函數(shù)定義(如libc庫),而系統(tǒng)調(diào)用是通過軟中斷想內(nèi)核態(tài)發(fā)出的請求;
2.???????? 一個API沒有必要對應(yīng)一個特定的系統(tǒng)調(diào)用。API可能直接提供用戶態(tài)服務(wù),如數(shù)學函數(shù);有些API函數(shù)可能調(diào)用幾個系統(tǒng)調(diào)用;幾個API函數(shù)可能調(diào)用同一系統(tǒng)調(diào)用(如malloc,calloc,free均使用brk系統(tǒng)調(diào)用實現(xiàn))。
3.???????? POSIX標準針對API而不是針對系統(tǒng)調(diào)用,判斷一個系統(tǒng)是否與POSIX兼容,要看它是否提供了一組合適的API。
4.???????? 從應(yīng)用程序設(shè)計者的角度看,兩者的差別僅在于名字、參數(shù)、返回值的不同;從內(nèi)核設(shè)計者的角度看,系統(tǒng)調(diào)用屬于內(nèi)核,而API不屬于內(nèi)核。
?
3. 內(nèi)核如何處理系統(tǒng)調(diào)用?
1.???????? 每一個系統(tǒng)調(diào)用擁有一個系統(tǒng)調(diào)用號的標識,當用戶態(tài)請求系統(tǒng)調(diào)用時,需傳遞系統(tǒng)調(diào)用號及其它信息作為參數(shù),eax寄存器用于傳遞系統(tǒng)調(diào)用號(同時也用于傳遞返回值,系統(tǒng)調(diào)用號與返回值類型相同)。內(nèi)核從寄存器讀到系統(tǒng)調(diào)用的參數(shù),并執(zhí)行對應(yīng)的系統(tǒng)調(diào)用服務(wù)例程。
2.???????? 下圖顯示了應(yīng)用程序、相應(yīng)的封裝例程、系統(tǒng)調(diào)用處理程序、系統(tǒng)調(diào)用服務(wù)例程之間的關(guān)系。xyz()是應(yīng)用程序的調(diào)用接口,xyz在libc中的調(diào)用實現(xiàn)通過調(diào)用SYSCALL匯編指令實現(xiàn),該指令使得CPU切換到內(nèi)核態(tài)(SYSEXIT反之);內(nèi)核態(tài)通過sys_call系統(tǒng)調(diào)用處理程序來最終調(diào)用xyz的服務(wù)例程sys_xyz()。
???
3.???????? 為了將系統(tǒng)調(diào)用號與相應(yīng)的服務(wù)例程關(guān)聯(lián)起來,內(nèi)核利用一個系統(tǒng)調(diào)用分派表,該表存放在sys_call_table數(shù)組中,有NR_syscalls個表項,第n個表項包含系統(tǒng)調(diào)用號為n的服務(wù)例程的地址。
?
?
4. 如何進入和退出系統(tǒng)調(diào)用?
本地應(yīng)用可以通過兩種方式調(diào)用系統(tǒng)調(diào)用:
1.???????? 執(zhí)行int $0x80匯編語言指令(老版本linux中從用戶態(tài)切換到內(nèi)核態(tài)的唯一方式)
2.???????? 執(zhí)行sysenter匯編語言指令,Intel Pentium II微處理器引入該指令,linux2.6內(nèi)核支持這條指令。
同樣,內(nèi)核可通過兩種方式從系統(tǒng)調(diào)用退出,使CPU切換回到用戶態(tài):
1.???????? 執(zhí)行iret匯編語言指令
2.???????? 執(zhí)行sysexit匯編語言指令
對以上兩種方式涉及到匯編代碼,我也解釋不太清楚,更詳細的了解,請參考《深入理解linux內(nèi)核》。
?
5. 系統(tǒng)調(diào)用參數(shù)如何傳遞?
1.???????? 普通C函數(shù)的參數(shù)傳遞是通過把參數(shù)值寫入到活動的程序棧(用戶態(tài)或內(nèi)核態(tài)堆棧)實現(xiàn)的,而系統(tǒng)調(diào)用同時跨越內(nèi)核態(tài)和用戶態(tài),同時操作兩個棧是很復(fù)雜的,而采用下面的方式(寄存器傳遞參數(shù))將使得系統(tǒng)調(diào)用處理程序與其它異常處理程序的結(jié)構(gòu)類似。
2.???????? 在發(fā)出系統(tǒng)調(diào)用之前,系統(tǒng)調(diào)用的參數(shù)被寫入到CPU的寄存器,然后在調(diào)用系統(tǒng)服務(wù)例程之前,內(nèi)核再把存放在CPU中的參數(shù)拷貝到內(nèi)核態(tài)堆棧(系統(tǒng)調(diào)用服務(wù)例程是普通的C函數(shù))。
3.???????? 使用寄存器傳遞參數(shù)必須滿足:每個參數(shù)的長度不能超過寄存器的長度(容易解決,長度不夠,可以通過傳遞參數(shù)的地址解決),并且參數(shù)的個數(shù)不能超過6個(系統(tǒng)調(diào)用號除外),因為80x86處理器的寄存器的數(shù)量是有限的(用于存放調(diào)用號和調(diào)用參數(shù)的寄存器是eax、ebx、ecx、edx、esi、edi、ebp)。
?
6. 如何保證系統(tǒng)調(diào)用的安全性?
內(nèi)核在滿足用戶的系統(tǒng)調(diào)用請求前,必須仔細的檢查所有的系統(tǒng)調(diào)用參數(shù),如write系統(tǒng)調(diào)用的參數(shù)fd,內(nèi)核需檢查fd是否對應(yīng)于一個打開的文件,該文件是否允許寫操作等,這些檢查操作依賴于系統(tǒng)調(diào)用本身,也依賴于特定的參數(shù)。但有一種檢查對所有的系統(tǒng)調(diào)用是通用的,只要參數(shù)指定的是地址,內(nèi)核必須檢查它是否屬于用戶地址空間,可通過檢查地址所在的線性區(qū),或直接與PAGE_OFFSET對比等兩種方式實現(xiàn)(linux2.2開始實現(xiàn)第二種方式)。
?
7. 內(nèi)核如何訪問用戶態(tài)數(shù)據(jù)?
系統(tǒng)調(diào)用服務(wù)例程需要非常頻繁的讀寫進程地址空間的數(shù)據(jù),Linux提供一組宏來實現(xiàn)這個目的(__開頭的宏不包含對線性地址的有效性檢查)。
get_user? __get_user?? 從用戶空間讀一個整數(shù)(1、2或4個字節(jié))
put_user? __put_user?? 向用戶空間寫一個整數(shù)(1、2或4個字節(jié))
copy_from_user __copy_from_user? 從用戶空間復(fù)制任意大小的塊
copy_to_user? __copy_to_user? 把任意大小的塊復(fù)制到用戶空間
strncpy_from_user ?__strncpy_from_user? 從用戶空間復(fù)制一個以null結(jié)束的字符串
strlen_user? strnlen_user? 返回用戶空間以null結(jié)束的字符串的長度
clear_user __clear_user 用0填充用戶空間的一個內(nèi)存區(qū)域
?
8. 在內(nèi)核態(tài)能否調(diào)用系統(tǒng)調(diào)用?
盡管系統(tǒng)調(diào)用主要由內(nèi)核態(tài)進程使用,但也可以被內(nèi)核線程調(diào)用,內(nèi)核線程不能使用庫函數(shù)。linux定義了7個從_syscall0到_syscall6的一組宏來封裝相應(yīng)例程,宏名中的數(shù)字0-6對應(yīng)著系統(tǒng)調(diào)用所用的參數(shù)個數(shù)(系統(tǒng)調(diào)用號除外)。每個宏需要2 + 2 * n個參數(shù)(n為系統(tǒng)調(diào)用參數(shù)的個數(shù)),前兩個參數(shù)是系統(tǒng)調(diào)用號返回值類型和名字;每一對附加參數(shù)指明相應(yīng)的系統(tǒng)調(diào)用參數(shù)的類型和名字。
轉(zhuǎn)載于:https://www.cnblogs.com/yunnotes/archive/2013/04/19/3032426.html
總結(jié)
以上是生活随笔為你收集整理的Linux系统调用FAQ的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DWR入门教程
- 下一篇: 十大不变计算机网络安全法则