《Linux內核設計與實現》第五章學習筆記編程
姓名:王瑋怡 學號:20135116函數
1、與內核通訊學習
在Linux中,系統調用是用戶空間訪問內核的惟一手段;除異常和陷入外,它們是內核的惟一合法入口。spa
2、API、POSIX、C庫設計
一、API3d
通常狀況下,應用程序經過在用戶空間實現的應用編程接口(API)來編程,而不是直接經過系統調用。指針
二、POSIXblog
在Unix世界中,最流行的應用編程接口是基於POSIX標準的。接口
三、C庫進程
C庫實現了Unix系統的主要API,包括標準C庫函數和系統調用接口。此外,C庫提供了POSIX的絕大部分API。
四、POSIX、API、C庫以及系統調用間的關係
3、系統調用(syscall)
一、系統調用號
在Linux中,每一個系統調用被賦予一個系統調用號。當用戶空間的進程執行一個系統調用時,用系統調用號來指明到底執行哪一個系統調用。
*特色:
(1)一旦分配就不能再有任何改變,而且若是一個系統調用被刪除,它所佔有的系統調用號也不容許被回收利用,內核將系統調用表中已註冊過的系統調用號記錄存儲在sys_call_table中
(2)「未實現」系統調用sys_ni_syscall(),只能返回-ENOSYS,專門針對無效的系統調用而設
二、Linux系統調用快速的緣由
(1)Linux上下文切換時間短,進出內核簡潔高效
(2)系統調用處理程序和每一個系統調用自己十分簡潔
4、系統調用處理程序
因爲內核駐留在受保護的地址空間上,用戶空間的程序沒法直接執行內核代碼,不能直接調用內核空間中的函數。應用程序通知內核的機制是靠軟中斷實現的:經過引起一個異常來促使系統切換到內核態去執行異常處理程序(系統調用處理程序)
在x86系統上預約義的軟中斷是中斷號128,經過int $0x80指令觸發該中斷,切換到內核態執行第128號異常處理程序——system_call
一、指定恰當的系統調用
全部的系統調用陷入內核的方式爲:陷入內核空間,並將系統調用號一併傳給內核(x86上經過eax寄存器傳遞)。system_call()函數將系統調用號與NR_syscalls做比較:
(1)系統調用號大於或等於NR_syscalls:return -ENOSYS
(2)系統調用號小於NR_syscalls:執行相應的系統調用 call *sys_call_table(,%rax,8) (x86-64位乘8,x86-32位乘4)
二、參數傳遞
大部分系統調用除了系統調用號外還須要外部的參數輸入,在x86-32系統上,ebx、ecx、edx、esi、edi按順序存放前五個參數(須要六個及以上的狀況很少見)。此外,給用戶空間的返回值經過eax寄存器傳遞。
5、系統調用的實現
一、實現系統調用
(1)決定它的用途;(2)肯定新系統調用的參數、返回值和錯誤碼;(3)設計接口
*注意:可移植性和健壯性
二、參數驗證
(1)系統調用必須檢查每一個參數,保證它們不只合法有效,並且正確。例如,與文件I/O相關的系統調用必須檢查文件描述符是否有效;與進程有關的函數必須檢查提供的PID是否有效。最重要的一種檢查是檢查用戶提供的指針是否有效。在接收一個用戶空間的指針前,內核必須保證:
(2)內核提供了兩個方法來完成必須的檢查和內核空間與用戶空間之間的數據來回拷貝:
*注意:copy_to_user()和copy_from_user()都有可能引發阻塞
(3)調用者可使用capable()函數檢查是否有權能對指定的資源進行操做,若是返回非0值則有權操做,返回0則無權操做
6、調用上下文
內核在執行系統調用時處於進程上下文。current指針指向當前任務,引起系統調用那個進程。在進程上下文中,內核能夠休眠(例如在系統調用阻塞或顯式調用schedule()時)而且能夠被搶佔。
系統調用返回的時候,控制權仍然在system_call()中,它最終會負責切換到用戶空間,並讓用戶進程繼續執行下去。
一、綁定一個系統調用的最後步驟
註冊成正式的系統調用的步驟:
(1)在系統調用表的最後加一個表項(從0開始算起)
(2)系統調用號必須定義於<asm/unistd.h>中
(3)系統調用必須被編譯進內核映象(不能被編譯成模塊)
二、從用戶空間訪問系統調用
Linux自己提供了一組宏,用於直接對系統調用進行訪問:_syscalln(),其中n的範圍爲0到6,表明須要傳遞給系統調用的參數個數。對每一個宏來講,都有2+2*n個參數,第一個參數對應着系統調用的返回值類型,第二個參數是系統調用名稱,再之後是按照系統調用參數的順序排列的每一個參數的類型和名稱。
三、採用系統調用做爲實現方法的利弊和代替方法
(1)創建一個系統調用的好處:
(2)創建系統調用的弊端:
(3)代替方法: