添加系统调用函数头文件
在include/linux/syscalls.h文件中的#endif前添加自己的系统调用函数声明,内容如下:
asmlinkage long sys_test(void);
添加系统调用实现源码
随便找一个文件,我们在这个文件中添加系统调用的源码SYSCALL_DEFINE0(test) ,内容如下:
SYSCALL_DEFINE0(test)
{
printk("Hello world!\n");
return 0;
}
这里的 SYSCALL_DEFINE0宏表示我们的系统调用是无参的,该宏在上面syscalls.h头文件中定义。 SYSCALL_DEFINE0的参数个数为一个,SYSCALL_DEFINEn的函数个数是n个
在系统调用表中添加相应的表项
添加系统调用向量,在arch/x86/syscalls/syscall_64.tbl文件中添加系统调用号和系统调用服务程序入口(如果是32位系统,则修改syscall_32.tbl文件),在313号系统调用后面添加如下内容:
314 common test sys_test
系统调用会去查找sys_call_table这个数组并找到对应的系统调用函数去执行,注意其中有一个关键函数do_ni_syscall,(no implement syscall),当系统调用遇到一些限制或者问题时会跳转到该函数去执行。
arch/arm64/kernel/sys.c:
/*
* The sys_call_table array must be 4K aligned to be accessible from
* kernel/entry.S.
*/
void * const sys_call_table[__NR_syscalls] __aligned(4096) = {
[0 ... __NR_syscalls - 1] = sys_ni_syscall,
#include <asm/unistd.h>
};
这个数组在创建时首先会把所有的数组成员设置为sys_ni_syscall,而后根据asm/unistd.h中的内容做进一步初始化。其实最终该头文件会把include/uapi/asm-generic//unistd.h包含进来,也就是这个头文件会是最终定义数组的地方。如下所示:
__SYSCALL(__NR_bpf, sys_bpf)
#define __NR_execveat 387
__SYSCALL(__NR_execveat, compat_sys_execveat)
#define __NR_userfaultfd 388
__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
#define __NR_membarrier 389
__SYSCALL(__NR_membarrier, sys_membarrier)
#define __NR_mlock2 390
__SYSCALL(__NR_mlock2, sys_mlock2)
#define __NR_copy_file_range 391
__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
#define __NR_preadv2 392
__SYSCALL(__NR_preadv2, compat_sys_preadv2)
#define __NR_pwritev2 393
__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
我们添加系统调用之后也需要在此数组中添加一个元素,例:
#define __NR_test 394
__SYSCALL(__NR_test, sys_test)
在数组中添加元素之后,还需要更新这个数组元素的个数,例:
arch/arm64/include/sam/unistd.h
#define __NR_compat_syscalls 395//394+1
添加系统调用号
他在unistd.h的文件中,每个系统调用号都已_NR_开头,我们添加系统调用号如下所示:
#define __NR_test 290
__SYSCALL(__NR_test, sys_test)
#undef __NR_syscalls
#define __NR_syscalls 292//291+1
应用测试程序
我们创建一个应用测试程序,源码如下所示:
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
int main(void)
{
long ret= syscall(290);
printf("%s %d ret = %d\n", __func__,__LINE__,ret);
return 0;
}