应用程序首先用适当的值填充到寄存器中,然后调用一个特殊的指令跳转到内核的固定的位置,内核根据应用程序填充的固定的值来找到相应的函数执行。
比如像如下程序:
1) 适当的值
在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)
/* 7 was sys_waitpid */
#define __NR_creat (__NR_SYSCALL_BASE+ 8)
2) 特殊的指令
a) 在inter Cpu中,这个指令由中断0X80实现
b) 在ARM中,这个指令是SWI
3)固定的位置
在ARM体系中,应用程序跳转到的固定内核位置是ENTRY(vector_swi)<entry-common.s>
4)相应的函数
内核根据应用程序传递来的系统调用号,从系统调用表sys_call_table找相应的内核函数。
CALL(sys_exit)
我们现在知道了其工作原理,下面我们就来添加一个我们自己的的系统API
1) 添加新的内核函数(kernel\sys.c)
asmlinkage int sys_add(int a,int b)
{
return a +b;
}
// asmlinkage:使用堆栈传递参数
2) 更新头文件unistd.h,添加我们的系统调用号
#define __NR_add (__NR_SYSCALL_BASE+ 361)
3)跟新系统调用表(kernel/call.s)
CALL(sys_add)
测试程序:
#include<stdio.h>
#include<unistd.h>
int main()
{
int result;
result = syscall(361,1,2);
printf(“%d\n”,result);
}