系统调用实现机制

一个Linux系统分为三个层次:用户层、核心层、硬件层。

其中系统调用是用户层与核心层的边界,通过系统调用进程可由用户层转入核心层,在核心层完成指定服务请求后,再返回用户层。

系统调用接口看起来和C程序中的普通函数调用很相似,它们通常是通过库把这些函数调用映射成进入操作系统所需要的原语。

这些操作原语只是提供一个基本功能集,而通过库对这些操作的引用和封装,可以形成丰富而且强大的系统调用库。这里体现了机制与策略相分离的编程思想——系统调用只是提供访问核心的基本机制,而策略是通过系统调用库来体现。

 

每个进程都有自己的地址空间,进程的地址空间分为两部分:用户空间和内核空间。在用户态,只能访问进程的用户空间;在内核态,可以访问进程的全部地址空间。

地址空间中的地址是逻辑地址,通过系统段面式的管理机制,访问的实际内存要做二级地址转换,即:逻辑地址-->线性地址-->物理地址。

 

系统调用在使用时和一般的函数调用很相似,但是二者是有本质性区别的,函数调用不能引起从用户态到核心态的转换,而正如前面提到的,系统调用需要有一个状态转换。

在每种平台上,都有特定的指令可以使当前线程由用户态转换为核心态,这种指令称作操作系统陷入(operatingsystemtrap)。线程通过执行陷入指令,便可以在核心态运行系统调用代码。

在Linux中是通过软中断来实现这种陷入的,在x86平台上,中断指令是int0x80。也就是说在Linux中,系统调用的接口是一个中断处理函数。

 

系统调用号:

核心中为每个系统调用定义了一个唯一的编号,这个编号的定义在linux/include/asm/unistd.h中,编号定义如下所示:

#define__NR_exit1

#define__NR_fork2

#define__NR_read3

#define__NR_write4

......

用户在调用一个系统调用时,系统调用号作为参数传递给中断0x80,而该标号实际上是后面将要提到的系统调用表(sys_call_table)的下标,通过该值可以找到相映系统调用的处理函数地址。

 

系统调用表

系统调用表记录了各个系统调用处理函数的入口地址,以系统调用号为偏移量很容易的能够在该表中找到对应处理函数地址。在linux/include/linux/sys.h中定义的NR_syscalls表示该表能容纳的最大系统调用数,NR_syscalls=256。

系统调用表的定义方式如下:(linux/arch/i386/kernel/entry.S)

ENTRY(sys_call_table)

.longSYMBOL_NAME(sys_ni_syscall)

.longSYMBOL_NAME(sys_exit)

.longSYMBOL_NAME(sys_fork)

.longSYMBOL_NAME(sys_read)

.longSYMBOL_NAME(sys_write)

......

 

系统调用的关键问题是:从用户模式到内核模式的转换、堆栈的切换、参数的传递。

具体怎样通过中断处理函数实现系统调用,如下文详细介绍。

1、在系统启动时,对INT0x80进行初始化,下面将描述其过程:

 1.1、调用汇编子程序setup_idt(linux/arch/i386/kernel/head.S)初始化中断描述符表,这时所有中断入口函数偏移地址都被设为ignore_int;

 1.2、调用Start_kernel()(linux/init/main.c)时,Start_kernel()会调用trap_init()(linux/arch/i386/kernel/trap.c)函数设置中断描述符表。在该函数里,实际上是通过调用函数set_system_gate(SYSCALL_VECTOR,&system_call)来完成该项的设置的。其中的SYSCALL_VECTOR就是0x80,而system_call则是一个汇编子函数,它即是中断0x80的处理函数。

2、线程调用“系统调用函数”时,产生1个0x80的软中断。

3、中断执行函数system_call()中,实际完成了以下几条操作:

 3.1、执行SAVE_ALL,首先获取当前线程的内核栈空间地址;把当前用户栈空间地址保存在到内核栈中;设置栈指针寄存器内容为内核栈空间地址;

 3.2、然后可以执行系统调用的处理函数(系统调用表中的系统调用处理函数,eg:sys_fork(),sys_read()等),并访问内核空间的内存地址了。

 3.3、执行RESTORE_ALL,来弹出所有被SAVE_ALL压入核心栈的内容,并恢复用户态;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值