我正在研究如何在内核代码中实现系统调用,并且我专注于x86架构,但是,我很难理解汇编代码和部分系统调用表的进入(或调用函数?)(就我所知,entry.S文件使用宏来"准备"用于系统调用),以及& #39;一个神秘的是:
ia32_do_call:
IA32_ARG_FIXUP
call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
由于我使用网站lxr.free-electrons.com,我使用自由文本搜索来查看该功能是如何实现的,以便进一步理解。我碰到过这个:
const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
/*
* Smells like a compiler bug -- it doesn't work
* when the & below is removed.
*/
[0 ... __NR_ia32_syscall_max] = &compat_ni_syscall,
#include <asm/syscalls_32.h>
};
这里发生了什么?
答案 0 :(得分:1)
我也对该文件感到惊讶,因此,如果您到达这里,我会留下一些指针来帮助您。
首先,sys_call_ptr_t
在include/asm/syscall.h
中定义为:
typedef long (*sys_call_ptr_t)(const struct pt_regs *);
因此,ia32_sys_call_table
是我们所期望的函数指针数组。接下来,使用称为designated initializers的gcc扩展名初始化该数组(由于this question)。初始化的第一部分将表的每个条目都指向一个名为sys_ni_syscall
的函数(我很确定,它似乎是通过一堆宏来创建的……)。这是在文件kernel/sys_ni.c
中定义的:
/*
* Non-implemented system calls get redirected here.
*/
asmlinkage long sys_ni_syscall(void)
{
return -ENOSYS;
}
最后,通过查看两件事可以理解文件<asm/syscalls_32.h>
的包含。首先,转到entry/syscalls/
,然后运行
bash syscalltbl.sh syscall_32.tbl gen.c
并查看gen.c
的内容。现在,从entry/syscall_32.c
看这个宏:
#define __SYSCALL_I386(nr, sym) [nr] = __ia32_##sym,
在这一点上,也许还有一些grep
,这个文件应该不会那么神秘。