1 系统调用的基础
应用程序通过0x80号中断进入系统调用,所以首先要在硬件机制上铺好进入中断的道路
这是在系统初始化进行的:
void __init trap_init(void)
{
...
set_system_gate(SYSCALL_VECTOR,&system_call);
...
}
2 系统调用表
在IA32架构下,内核里所有的系统调用的入口函数,都被放入系统调用表中
在arch/i386/kernel/syscall_table.S中
ENTRY(sys_call_table)
.long sys_restart_syscall
.long sys_exit
.long sys_fork
.long sys_read
.long sys_write
.long sys_open /* 5 */
.long sys_close
......
}
这张表其实就是个函数指针表,这张表是系统调用总的转发依据
在进入system_call之后,内核以eax的系统调用号为索引,调用对应的系统调用入口函数:
syscall_call:
#eax存放着系统调用号,这里进入对应的系统调 用
call *sys_call_table(,%eax,4)
# 从系统调用中返回,eax里存放系统调用的结果
movl %eax,PT_EAX(%esp)
3 系统调用的截获
我们就是要在进入系统调用之前和之后截获系统调用
首先准备我们的系统调用进入和退出时的截获函数
asmlinkage void senix_sys_enter(int call)
{
printk("senix_sys_enter %d %s %d/n",current->pid,current->comm,call);
}
asmlinkage void senix_sys_exit(int ret)
{
printk("senix_sys_exit %d %s %d/n",current->pid,current->comm,ret);
}
然后修改进入系统调用的流程
syscall_call:
#保存eax里的系统调用号,防止被修改
pushl %eax
#进入我们的截获函数,在里面截取系统调用号(也可截获其他参数)
call senix_sys_enter
#恢复系统调用号
popl %eax
call *sys_call_table(,%eax,4)
#保存eax里的系统调用返回值,防止被修改
pushl %eax
#进入我们的截获函数,在里面截取系统返回值
call senix_sys_exit
#恢复系统调用返回值
popl %eax
movl %eax,PT_EAX(%esp)
...
4 讨论
以上代码在本人的机器上调试成功,内核版本为linux-2.6.21.5
===============================================================
讨论 linux_kernel_2_6@yahoo.com.cn
未经允许请勿用于商业用途
wangsen
===============================================================