ie传递给系统调用的数据区域太小_【Linux系列】系统调用
在現代OS中,內核提供了用戶進程與內核進行交互的一組接口。這些接口讓應用程序受限地訪問硬件設備,提供了創建新進程并與已有進程進行通信的機制,也提供了申請OS其他資源的能力。
系統調用在用戶空間進程和硬件設備之間添加了一個中間層。該層主要作用有三個:
為用戶空間提供了一種硬件的抽象接口
保證了系統的穩定和安全
每個進程都運行在虛擬系統中,而在用戶空間和系統的其余部分提供這樣一層公共接
??Linux—OS的系統調用是用戶空間訪問內核的唯一手段;除異常和陷入外,是內核唯一的合法入口。實際上其他的像設備文件和/proc之類的方式,最終還是通過系統調用進行訪問的。
1.API: 一般情況下,應用程序通過在用戶空間實現的應用編程接口API而不是直接通過系統調用來編程。因為application使用的API實際上并不需要和內核提供的系統調用對應。一個API定義了一組應用程序使用的編程接口。 ??在Unix中最流行的應用編程接口是基于POSIX標準的。 ???POSIX是由IEEE的一組標準組成,其目標是提供一套大體上基于Unix的可移植OS標準。在大多數Unix系統上,根據POSIX定義的API函數和系統調用之間有著直接關系;非Unix系統如Windows也提供了與POSIX兼容的庫。 Linux的系統調用作為C庫的一部分提供。C庫實現了Unix系統的主要API,同時提供了POSIX的絕大部分API。Unix的系統調用抽象出了用于完成某種確定的目的函數,不需要內核關心函數的使用。 |
系統調用syscall通過C庫中定義的函數調用來進行,會通過一個long類型的返回值來表示成功or錯誤。在出現錯誤時C庫會把錯誤碼寫入errno全局變量。通過調用perror()庫函數可以把該變量翻譯成用戶可以理解的錯誤字符串。
~如何定義系統調用?
1.注意函數聲明中的asmlinkage限定詞,這是一個編譯指令,通知編譯器僅從棧中提取該函數的參數。所有的syscall都需要這個asmlinkage限定詞。
2.函數返回long類型。為了保證32 bit和64 bit系統兼容,syscall在用戶空間(返回int)和內核空間(返回long)由不同的返回值類型。
3.注意系統調用get_pid()在內核中被定義成sys_getpid()——命名規則
【系統調用號】
在Linux中,每個系統調用syscall被賦予一個唯一系統調用號。
當用戶空間的進程執行一個系統調用時,這個系統調用號就用來指明到底是要執行哪個系統調用;進程不會提及系統調用的名稱。
???Linux有一個“未實現”系統調用sys_ni_syscall(),只返回無效的系統調用錯誤號-ENOSYS。
??內核sys_call_table記錄了系統調用表中的所有已注冊過的syscall列表,該表為每一個有效的系統調用指定了唯一的系統調用號。
【syscall性能】
Linux系統調用比其他許多OS執行都要快。
很短的上下文切換時間
系統調用處理程序和每個系統調用本身都很簡潔
【系統調用處理程序】
用戶空間的程序無法直接執行內核代碼,因為內核駐留在受保護的地址空間上。那么需要通知內核要執行一個系統調用,其機制是靠軟中斷實現的。
軟中斷~通過引發一個異常來促使系統切換到內核態去執行異常處理程序,此時的異常處理程序即為系統調用處理程序。 ??X86系統上預定義的軟中斷是128,通過int$0x80指令觸發該中斷。這條指令會觸發一個異常導致系統切換到內核態并執行第128號異常處理程序/系統調用處理程序system_call()。 ??X86增加了sysenter指令提供了更快、更專業的陷入內核執行系統調用的方式。 |
A.指定恰當的syscall
因所有的系統調用陷入內核方式一樣,必須把系統調用號一并傳給內核。在X86上,系統調用號是通過eax寄存器傳遞給內核的。
system_call()函數通過將給定的系統調用號與NR_syscalls做比較來檢查其有效性。若 >= NR_syscalls,該函數就返回-ENOSYS。否則就執行相應的syscall:
call *sys_call_table(, %rax, 8)
B.參數傳遞
除了系統調用號以外,大部分系統調用都還需要一些外部的參數輸入。可以像傳遞系統調用號把這些參數從用戶空間傳給內核。
在X86-32系統上,ebx、ecx、edx、esi和edi按照順序存放前5個參數。
【系統調用實現】
1.系統調用實現
每個系統調用都應該有一個明確的用途。在Linux中不提倡采用多用途的syscall(一個系統調用通過傳遞不同的參數值來選擇完成不同的工作)。Unix主張提供機制而不是策略。
系統調用的接口應該力求簡潔,參數盡可能少。
系統調用的語義和行為非常關鍵,因為應用程序依賴于它們。
盡量為將來多考慮,考慮其擴展性。
2.參數驗證
系統調用必須仔細檢查它們所有的參數是否合法有效。syscall在內核空間執行,如果任由用戶將不合法的輸入傳遞給內核,那么系統的安全和穩定將受到影響。
??最重要的一種檢查就是檢查用戶提供的指針是否有效。在接收一個用戶空間的指針之前,內核必須保證:
指針指向的內存區域屬于用戶空間。~進程絕不能欺騙內核去讀內核空間的data
指針指向的內存區域在進程的地址空間里。~進程絕不能欺騙內核去讀其他進程的data
如果是讀,該內存應被標記為可讀;
如果是寫,該內存應被標記為可寫;
如果是可行,該內存應被標記為可執行
~進程絕不能繞過內存訪問限制~
內核提供了2個方法來完成必須的檢查和內核空間<=>用戶空間之間data的來回拷貝。
??內核無論何時都不能輕率地接受來自用戶空間的指針!??
1.copy_to_user():向用戶空間寫入data 該函數有3個參數,分別為進程空間中的目的內存地址、內核空間內的源地址、需要拷貝的data長度。 2.copy_from_user():從用戶空間讀取data 該函數有3個參數與1相似,把第二個參數指定位置上的data拷貝到第一個參數指定的位置上,拷貝的數據長度由第三個參數決定。 【返回值】 若失敗,返回的是沒能完成拷貝的數據字節數;若成功則為0。 |
新版本的Linux允許檢查針對特定資源的特殊權限。調用者可以使用capable()函數來檢查是否有權對指定的資源進程操作(0無非0有)。默認情況下,屬于超級用戶的進程擁有所有權利而非超級用戶沒有任何權利。Linux/capability.h包含一份所有這些權能和其對應的權限列表。
【系統調用上下文】
內核在執行syscall時處于進程上下文。在進程上下文中,內核可以休眠(如在系統哦給你調用阻塞or顯式調用schedule()時)并且可以被搶占。
休眠表明系統調用可以使用內核提供的絕大部分功能。
可搶占表明當前的進程可被其他進程搶占。
??????因為新的進程可能使用相同的系統調用,所以必須保證系統調用是可重入的。
當系統調用返回時,控制權仍然在system_call()中,它最終負責切換到用戶空間并讓用戶進程繼續執行下去。
1.綁定一個系統調用的最后步驟
當編寫完一個系統調用后,要把它注冊成一個正式的系統調用。如下步驟:
在系統調用表的最后加入一個表項。??index從0開始
對于所支持的各種體系結構,系統調用號都必須定于中
系統調用必須被編譯進內核映像(而不能編譯成模塊)。需要把它放入kernel/下的一個相關文件即可。
2.從用戶空間訪問系統調用
通常系統調用靠C庫支持。用戶程序通過包含標準文件并和C庫鏈接,就可使用syscall。
??Linux本身提供了一組宏,用于直接對系統調用進行訪問。它會設置好寄存器并調用陷入指令。這些宏是_syscalln(),其中n的范圍[0, 6],代表需要傳遞給系統調用的參數個數。對于每個宏,都有2 + 2*n個參數。
~例如:
open()系統調用定義如下:
long open(const char *filename,int flags, int mode)而不靠庫支持,直接調用此系統調用的宏的形式如下:
#define NR_open 5_syscall3(long,??open,?const?char?*filename,int?flags,?int?mode)其中long為返回值類型,open為系統調用名稱,后面為參數信息。
該宏會被擴展成為內嵌匯編的C函數;由匯編語言執行。將系統調用號和參數壓入寄存器并觸發軟中斷來陷入內核。
3.why不通過系統調用的方式實現???
~建立一個new系統調用的好處:
系統調用創建容易且使用方便
Linux系統調用的高性能顯而易見
引發的問題:
需要一個內核在處于開發版本時由官方分配的系統調用號
系統調用被加入穩定內核后就被固化了,為了避免應用程序崩潰,它的接口不允許改動
需要將系統調用分別注冊到每個需要支持的體系結構中去
在腳本中不容易調用系統調用,也不能從文件系統直接訪問系用調用
由于需要系統調用號,因此在住內核樹外是很難維護和使用系統調用的
如果僅僅進行簡單的信息狡猾,系統調用就大材小用了
??不要以為你以為的就是你以為的~這很哲學??
~替代方法:
實現一個設備節點,并對此實現read()和write()。使用ioctl()對特定的設置進行操作or對特定的信息進行檢索。
像信號量接口,可以用文件描述符來表示。因此也就可以按上述方式對其操作
把增加的信息作為一個文件放在sysfs的合適位置
Linux系統盡量避免每出現一種新抽象就簡單的加入一個new系統調用。新系統調用增添頻率很低也反映出了Linux是一個相對穩定且功能較為完善的OS。
總結
以上是生活随笔為你收集整理的ie传递给系统调用的数据区域太小_【Linux系列】系统调用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python对象列表转换为字典_pyth
- 下一篇: pycharm安装python包_Pyc