1. Linux體系結構
Linux系統的地址空間分爲用戶空間和內核空間,通過系統調用和硬件中斷能夠完成從用戶空間到內核空間的轉移。
2. 系統調用接口
① 一般情況下,用戶進程不能訪問內核空間。Linux內核中提供了一組用於實現各種系統功能的子程序,用戶可以調用它們訪問Linux內核的數據和函數,這些子程序稱爲系統調用接口(SCI)。
② 系統調用和普通函數的區別:系統調用由操作系統內核實現,運行於內核態;普通函數調用由函數庫或用戶自己提供,運行於用戶態。
3. 系統調用分類:主要分3大類
① 進程控制類
* fork
* clone
* execve
...
② 文件控制類
* fcntl
* open
* read
...
③ 系統控制類
* ioctl
* reboot
...
4. 系統調用工作原理
系統調用工作原理是(1)進程先用適當的值填充寄存器(R7),(2)然後調用一個特殊的指令(swi),(3)這個指令會讓用戶程序跳轉到一個事先定義好的內核中的一個位置(vector_swi),(4)這位置的代碼會根據寄存器(R7)的值從表sys_call_table中查找相應的函數。
(1)適當的值:系統調用號,定義於文件arch\arm\include\asm\unistd.h中。
#define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0) #define __NR_exit (__NR_SYSCALL_BASE+ 1) #define __NR_fork (__NR_SYSCALL_BASE+ 2) #define __NR_read (__NR_SYSCALL_BASE+ 3) #define __NR_write (__NR_SYSCALL_BASE+ 4) #define __NR_open (__NR_SYSCALL_BASE+ 5) #define __NR_close (__NR_SYSCALL_BASE+ 6)
(2)特殊的指令
* 在X86 CPU中,這個指令由中斷0x80實現
* 在ARM中,這個指令是SWI(Software interrupt:軟中斷指令),現在重命名爲SVC
(3)固定的位置:在ARM體系中,這個固定位置爲ENTRY(vector_swi)(arch\arm\kernel\entry-common.S)
(4)相應的函數:內核根據應用程序傳遞來的系統調用號,從系統調用表sys_call_table(sys_call_table中表項定於文件:arch\arm\kernel\calls.S)找到相應的內核函數。
5. 向Linux內核中添加新的系統調用
① 在內核代碼的某一位置添加函數,如:向kernel/printk.c中添加
void sys_print() { printk("Hello Kevin, this is a new system call\n"); }
② 把函數添加至sys_call_table,如:向arch\arm\kernel\calls.S中373行添加
CALL(sys_print)
③ 添加系統調用號,如:向arch\arm\include\asm\unistd.h中添加
#define __NR_sys_print (__NR_SYSCALL_BASE+361)
6. 新的系統調用測試
①應用層測試代碼方法1:
#include <sys/syscall.h> int main() { syscall(361); return 0; }
①應用層測試代碼方法2:
void SystemCallTest() { __asm__ ( "ldr r7, =361 \n" "swi \n" : : :"memory" ); } int main() { SystemCallTest(); return 0; }