linux添加一个系统调用(syscall)

添加系统调用函数头文件

在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;
}

 

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要给Linux增加一个系统调用,首先需要对Linux内核进行修改。具体的步骤如下: 1. 在内核源码中确定添加系统调用的位置。通常可以在`arch/x86/entry/syscalls`目录下找到系统调用表的文件,例如`syscall_64.tbl`。 2. 打开相应的系统调用表文件,添加一行来定义新的系统调用。每行包含系统调用号、系统调用名称和对应的处理函数。系统调用号是一个唯一的整数,用来标识系统调用。例如: ``` 336 common my_new_syscall sys_my_new_syscall ``` 3. 找到对应的处理函数所在的文件,通常在`kernel/sys.c`中。在该文件中添加一个新的函数来处理新的系统调用,函数名与上一步中的处理函数名称一致。在函数中实现具体的功能逻辑。 4. 编译内核,确保新的系统调用被包含在编译过程中。执行适当的编译命令,例如`make`。 5. 重新启动计算机,进入新编译的内核。 6. 在用户空间的程序中调用新的系统调用。通过C程序调用系统调用的实例代码如下: ```c #include <stdio.h> #include <unistd.h> #define __NR_my_new_syscall 336 int my_new_syscall() { return syscall(__NR_my_new_syscall); } int main() { int ret = my_new_syscall(); printf("My new system call returned %d\n", ret); return 0; } ``` 以上是向Linux内核中添加一个新的系统调用的基本过程。当然,具体实现会根据系统版本和内核的不同而有所差异,所以这只是一个大致的指导,具体操作还需参考内核版本和相应的文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值