文档介绍:linux 系统调用
一、linux 系统调用实现原理 1. 每一个系统调用通过单一的入口点,多路传入内核。eax寄存器用来标识当前应当调用的系统调用。这在C库中做了指定。 2. 当加载了系统C库索引和参数时,就会产生一个软件中断(0x80中断),进入中断服务程序,该中断服务会调用system_call函数,通过eax寄存器内容标识处理所用的系统调用。 3. 在通过几个简单测试后,使用syscall_call_table和eax寄存器标识来执行真正的系统调用。从sysytem_call返回后,执行syscall_exit,并调用resume_userspace返回应用空间,继续执行C库函数,然后进入应用程序。 二、 系统调用函数列表 ,定义了所有的系统调用函数和其调用号,如下所示:#define __NR_socketcall (__NR_SYSCALL_BASE+102)#define __NR_syslog (__NR_SYSCALL_BASE+103)#define __NR_setitimer (__NR_SYSCALL_BASE+104)#define __NR_getitimer (__NR_SYSCALL_BASE+105)#define __NR_stat (__NR_SYSCALL_BASE+106)#define __NR_lstat (__NR_SYSCALL_BASE+107)#define __NR_fstat (__NR_SYSCALL_BASE+108)
。
三、 系统调用的实现Linux中实现系统调用利用了0x86体系结构中的软件中断。软件中断和我们常说的中断(硬件中断)不同之处在于,它是通过软件指令触发而并非外设引发的中断,也就是说,又是编程人员开发出的一种异常(该异常为正常的异常),具体的讲就是调用int $0x80汇编指令,这条汇编指令将产生向量为0x80的编程异常。之所以系统调用需要借助异常来实现,是因为当用户态的进程调用一个系统调用时,CPU便被切换到内核态执行内核函数,而我们在i386体系结构部分已经讲述过了进入内核——进入高特权级别——必须经过系统的门机制,这里的异常实际上就是通过系统门陷入内核(除了int 0x80外用户空间还可以通过int3——向量3、into——向量4 、bound——向量5等异常指令进入内核,而其他异常无法被用户空间程序利用,都是由系统使用的)。我们更详细地解释一下这个过程。int $0x80指令的目的是产生一个编号为0x80的编程异常,这个编程异常对应的是中断描述符表IDT中的第128项——也就是对应的系统门描述符。门描述符中含有一个预设的内核空间地址,它指向了系统调用处理程序:system_call()(别和系统调用服务程序混淆,)。很显然,所有的系统调用都会统一地转到这个地址,但Linux一共有2、3百个系统调用都从这里进入内核后又该如何派发到它们到各自的服务程序去呢?别发昏,解决这个问题的方法非常简单:首先Linux为每个系统调用都进行了编号(0—NR_syscall),