《Unix高級編程學習筆記》 1git
POSIX、API、C庫和syscall之間的關係 github
long
類型的返回值(爲與64位的硬件體系結構保持兼容)errno
全局變量,經過perror()庫函數翻譯成用戶理解的錯誤字符串。SYSCALL_DEFINE0(###)
//定義內核中的系統調用getpid()的實現
//展開前
SYSCALL_DEFINE0(getpid)
{
return task_tgidvnr(current); //return current->tgid
}
//展開後
asmlinkage long sys_getpid(void){
return task_tgidvnr(current); //return current->tgid
}
複製代碼
用例:編程
//定義內核中的系統調用bar()的實現
//展開前
SYSCALL_DEFINE0(bar)
//展開後
asmlinkage long sys_bar()
複製代碼
注:用戶空間返回int
,內核空間返回long
安全
用於關聯繫統調用。用戶進程空間的進程執行一個系統調用時,使用系統調用號指明到底執行哪一個系統調用,且不會說起系統調用的名稱。bash
sys_ni_syscall()
返回-ENOSYS
,專門填補無效系統調用;x86-64
中,定義於arch/i386/kernel/syscall_64.c
中,併爲每一個系統調用指定惟一的系統調用號很高:上下文切換時間短,進出內核被優化得簡潔高效,系統調用處理程序和系統調用簡潔函數
告訴內核須要切換到內核態,讓內核表明應用程序在內核空間執行系統調用 實現機制: 系統調用處理程序:引起一個異常促使系統謝歡到內核態去執行異常處理程序,叫syscall_call()性能
system_call()
NR_syscalls
相比較,大於等於NR_syscalls則返回-ENOSYS,不然執行相應的系統調用call *sys_call_table(,%eax, 8)
//8表明系統調用表中表項以64位類型存放,則結果等於 系統調用號×4 用於查詢系統調用位置。
//x86-32則用4代替8
複製代碼
x86-32
系統中前五個參數放置在ebx, ecx, edx, esi和edi
中編寫完一個系統調用後,將其註冊誠正式的系統調用學習
<asm/unistd.h>
中一般,系統調用靠C庫支持,若是僅僅寫出系統調用,glibc庫並不支持,怎麼辦呢 答:宏_syscalln()
,其中n範圍爲0~6表明傳遞給系統調用的參數個數,功能爲設置好寄存器並調用陷入指令 例子:優化
//open()系統調用定義
long open(const char* filename, int flags, int mode)
複製代碼
不靠庫支持,直接調用此係統調用的宏形式ui
#define NR_open 5
_syscall3(long, open, const char*, filename, int, flags, int, mode)
複製代碼
在Android系統中,_syscall()
被syscall()
替代,且每一種Android支持的系統調用的參數形式都在Android源碼中被SYSCALLS.txt記錄,咱們能夠根據系統調用的知識,並結合SYSCALLS.txt,能夠很輕易地寫出本身對應的的syscall()。