總體流程:kill() -> kill.S -> swi陷入核心态 -> 從sys_call_table檢視到sys_kill -> ret_fast_syscall -> 回到使用者态執行kill()下一行代碼。
詳細過程概述
使用者程式在使用者空間通過軟中斷swi指令切入核心台,執行vector_swi處指令——這個指令産生軟體中斷,vector_swi指令在檔案/kenel/arch/arm/kernel/entry-common.S中定義。
跟異常處理程式一樣,首先保護現場(保護産生中斷的使用者空間現場),緊接着擷取系統調用的系統調用号(這個過程在使用者空間執行),以殺程序的kill()函數為例,使用者空間kill()定義位于kill.S,當調用kill時,系統先儲存r7内容,然後将_NR_kill值放入r7,再執行swi軟體中斷指令切換進核心态。
使用者空間kill的系統調用号為_NR_kill,使用者空間的系統調用号定義于/bionic/libc/kernel/uapi/asm-generic/unistd.h 。
(其中__NR_SYSCALL_BASE=0,也就是__NR_kill系統調用号=37。)
在Linux核心中,每個Syscall都有唯一的系統調用号對應。在核心中有與系統調用号對應的系統調用表,定義在檔案/kernel/arch/arm/kernel/calls.S
(到這裡可知37号系統調用對應sys_kill(),該方法所對應的函數聲明在syscalls.h檔案)
sys_kill()為核心空間的對應系統調用,對應執行過程的函數聲明在syscalls.h檔案
asmlinkage是gcc标簽,代表函數讀取的參數來自于棧中,而非寄存器。
sys_kill()定義在核心源碼找不到直接定義,而是通過syscalls.h檔案中的SYSCALL_DEFINE宏定義。
總結:
核心空間
1.系統調用的函數原型的指針:位于檔案/kernel/arch/arm/kernel/calls.S,格式為CALL(sys_xxx),定義了核心空間系統調用的目标函數入口
2.系統調用号的宏定義:位于檔案/kernel/arch/arm/include/Uapi/asm/unistd.h,記錄着核心空間的系統調用号,格式為#define__NR_xxx (__NR_SYSCALL_BASE+[num])
3.系統調用的函數聲明:位于檔案/kernel/include/linux/syscalls.h,格式為asmlinkage long sys_xxx(args …);
4.系統調用的函數實作:不同函數位于不同檔案,比如kill()位于/kernel/kernel/signal.c檔案,格式為SYSCALL_DEFINEx(x, sname, …)
使用者空間
1.系統調用号的宏定義:位于檔案/bionic/libc/kernel/uapi/asm-arm/asm/unistd.h,記錄着使用者空間的系統調用号,格式為#define__NR_xxx (__NR_SYSCALL_BASE+[num])。這個檔案就是由核心空間同名的頭檔案自動生成的,是以該檔案與核心空間的系統調用号是完全一緻。
2彙編定義相關函數的中斷調用過程:位于檔案/bionic/libc/arch-arm/syscalls/xxx.S,比如kill()位于kill.S,在使用者空間也有函數聲明,格式為:
先儲存,再内陷,發生系統調用。
其他:
新添加系統調用:除了上面的過程,還需要新增系統調用号還需要修改syscalls總個數,但強烈不建議自己新增系統調用号,盡量保持與linux kernel主線一緻,相容性更好。
-=------------------------------------————————————————————————————————————
Linux系統中使用者空間通路核心的手段:系統調用(一般通過中斷的方式),異常,陷入。系統調用是使用者空間通路核心的唯一合法手段。
中斷:一個硬體或者軟體請求,要求CPU暫停目前的工作,去處理更重要的事情。例子:在x86及其上可以通過int指令進行軟體中斷,而在磁盤完成讀寫操作後會向CPU發起硬體中斷。
中斷有兩個重要的屬性,中斷号和中斷處理程式。中斷号用來辨別不同的中斷,不同的中斷具有不同的中斷處理程式。在作業系統核心中維護着一個中斷向量表(Interrupt Vector Table),這個數組存儲了所有中斷處理程式的位址,而中斷号就是相應中斷在中斷向量表中的偏移量。