linux sys_call

每个系统调用都会有一个编号与之相对应。用户态调用一个系统调用,实际上调用运行时库(glibc)中的函数,runtime library会通过80号中断,陷入内核态,通过eax寄存器传递要调用系统调用编号,参数的传递通过寄存器或者copy_to_user等函数,实际通过页面缓存进行。然后根据调用号找到系统调用对应的内核函数的名字。

所有系统以及对应的调用号定义在:arch/x86/include/asm/unistd_32.h。在这里,我们要将系统调用的名字与编号相对应。

每个系统调用号与对应的内核函数的关系在: arch/x86/kernel/syscall_table_32.S中,这种对应关系是通过偏移来实现的,内核函数在这个表中的位置即是调用号。也就说通过调用号我们可以找到对应的内核函数。


内核函数的声明在文件:include/linux/syscalls.h

查找的过程是,首先在arch/x86/include/asm/unistd_32.h中寻找对应的系统调用的名字,得到对应的系统调用号,然后到了内核态,系统调用号就是在arch/x86/kernel/syscall_table_32.S表中的偏移,我们会得到实际的系统调用对应的内核函数。


那么给系统添加一个系统调用的过程如下:

1 在文件arch/x86/include/asm/unistd_32.h中添加

#define _NR_mysyscall  326 //不能与之前的已经重复,这个编号就是系统调用号,内核函数在 arch/x86/kernel/syscall_table_32.S表中的偏移。

#define _NR_syscalls 327 //修改总共的系统调用数目

2在arch/x86/kernel/syscall_table_32.S中末尾添加系统调用对应的内核函数.类似于:

.long sys_mycall

其偏移应当就是第一步定义的系统调用号

3 在include/linux/syscalls.h添加内核函数的声明:

类似于: asmlinkage long sys_mycall(int);

其实现需要在usr/src/linux/下创建一个文件夹mysyscall,在该文件夹中定义文件mysyscall.c,内容大概如下:

#include<linux/linkage.h>

asmlinkage long sys_mycall(int i)

{

return i+10;

}

asmlinkage是告诉编译器在内核栈上寻找参数。

4 调用该内核函数:

#include<linux/unistd.h>

#define __NR_mysyscall 317

_syscall1(long, mysyscall, int, i)

上面的代码使得生成了如下的系统调用:

long mysyscall(int i)

{

return syscall(__NR_mysyscall, i);

}
内核中提供了不同的syscall函数.

syscall需要传递系统调用号和一个参数,就会调用该系统调用号对应的内核函数。

而宏_syscall1需要的四个参数分别是返回值的类型,系统调用的名称,参数的类型,参数的名称。 系统调用号则是传递进来的名称前+__NR对应的宏的值。

也就说提供给用户态的系统调用名称最终是生成的,glibc中提供的很多系统调用就是直接通过脚本生成的。


syscall的含义,用法在不同的内核版本之间可能已经不同,但提供的功能大致相当。


5 动态修改系统调用的方法,大概过程是,设法获取到内存中运行的内核模块的syscall_table.s指定偏移的地址。修改或者添加一个新的子项,就是一个系统调用号对应的新的内核函数了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值