本文共 2822 字,大约阅读时间需要 9 分钟。
sys_call_table中保存了系统调用的处理地址,该表的初始化过程非常巧妙。
系统调用程序system_call会查找系统调用表以获得系统调用号对应的系统调用,并执行。// 定义位置:arch/x86/kernel/syscall_32.c#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;#include#undef __SYSCALL_I386#define __SYSCALL_I386(nr, sym, compat) [nr] = sym,typedef asmlinkage void (*sys_call_ptr_t)(void);extern asmlinkage void sys_ni_syscall(void);// sys_call_table是一个数组,其值为typedef void (*sys_call_ptr_t)(void)类型的函数指针 __visible const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { /* * Smells like a compiler bug -- it doesn't work * when the & below is removed. */ // 先对表中所有 __NR_syscall_max+1 项初始化为指向 sys_ni_syscall 的函数,该函数只返回 -ENOSYS,表示该系统调用未实现 [0 ... __NR_syscall_max] = &sys_ni_syscall,// syscalls_32.h是在编译时生成的#include };
该文件是在编译时生成的。编译内核的时候,当执行/arch/x86/syscalls/Makefile编译规则时,该文件会执行/arch/x86/syscalls/syscalltbl.sh,该脚本将同目录下的syscall_32.tbl文件作为输入,然后生成文件arch/x86/include/generated/asm/syscalls_32.h,这个文件正是sys_call_table定义中包含的文件。
## 32-bit system call numbers and entry vectors## The format is:### The abi is always "i386" for this file.#0 i386 restart_syscall sys_restart_syscall1 i386 exit sys_exit2 i386 fork sys_fork stub32_fork3 i386 read sys_read4 i386 write sys_write5 i386 open sys_open compat_sys_open6 i386 close sys_close
#!/bin/shin="$1"out="$2"grep '^[0-9]' "$in" | sort -n | ( while read nr abi name entry compat; do abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` if [ -n "$compat" ]; then echo "__SYSCALL_${abi}($nr, $entry, $compat)" elif [ -n "$entry" ]; then echo "__SYSCALL_${abi}($nr, $entry, $entry)" fi done) > "$out"
in和out分别代表的就是syscall_32.tbl和syscalls_32.h文件的路径。脚本读取syscall_32.tbl内容,然后构造语句__SYSCALL_abi(nr, entry,entry)"。
__SYSCALL_I386(0, sys_restart_syscall, sys_restart_syscall)__SYSCALL_I386(1, sys_exit, sys_exit)__SYSCALL_I386(2, sys_fork, stub32_fork)__SYSCALL_I386(3, sys_read, sys_read)__SYSCALL_I386(4, sys_write, sys_write)__SYSCALL_I386(5, sys_open, compat_sys_open)__SYSCALL_I386(6, sys_close, sys_close)__SYSCALL_I386(7, sys_waitpid, sys32_waitpid)__SYSCALL_I386(8, sys_creat, sys_creat)__SYSCALL_I386(9, sys_link, sys_link)__SYSCALL_I386(10, sys_unlink, sys_unlink)__SYSCALL_I386(11, sys_execve, stub32_execve)...
__SYSCALL_I386 是一个宏定义:#define __SYSCALL_I386(nr, sym, compat) [nr] = sym
const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { [0 ... __NR_syscall_max] = &sys_ni_syscall, [0] = sys_restart_syscall, [1] = sys_exit, [2] = sys_fork, [3] = sys_read, //...};
系统调用处理程序system_call执行call *sys_call_table(,%rax,4),即可转入系统调用函数进行真正处理。
转载地址:http://wwerb.baihongyu.com/