您的位置:首页 > 编程语言

【操作系统】编程技术--系统调用实现机理

2011-03-30 20:48 281 查看
linux系统调用实现机理

执行系统调用时会促发的一个宏

_syscallN(type,name,parameter1 type,...)

这是一个带参数宏,定义在unish.h中,用来展开系统调用,,N是可变的,表示系统调用函数的参数的个数,宏参数分别为系统调用函数返回类型,系统调用函数名,参数类型,参数名

其展开后如下:

#define _syscall0(type,name)

type name(void)

{

Long __res;

__asm__volatile(int $0x80

: "=a" (__res)

:""(__NR_##name));

__syscall_return(type,__res);

}

系统调用总控程序

所有的系统调用都是通过相应的接口函数进入内核里的系统调用总控程序,而由总控程序再调用/相应系统调用的核心函数,linux中这种内核陷入是通过0X80号中断实现的,系统总控程序功能如下:

1.取系统调用号

(1)系统调用入口地址表:

入口地址表详细给出了所有系统调用的核心函数名称及其序号

(2)系统调用号:

linux系统调用号就是系统调用入口地址表中位置的序号,如系统调用号为5的open函数,他在系统调用入口地址表中的位置序号是 5,其核心函数名 称是sys_open,提供给用户的系统调用名称与该系统调用的核心函数名称并不相同,系统调用接口函数将系统调 用号传递给内核,内核再根据系统调用号来定位其所对应的系统调用核心函数

2,根据系统调用号定位系统调用核心函数名称地址

3. 根据通用寄存器中的内容,从用户栈中取入口参数

4. 核心函数执行完毕后,将结果返回给用户程序

以getuid这个系统调用为例:

#include <linux/unistd.h>

int main()

{

int i = getuid();

}

获取当前进程的id号。

第一步:

当程序调用getuid时,便会调用头文件unistd.h中的定义的_syscall0(int ,getuid)这个宏

通过这个宏

getuid会被展开成以下代码:

int getuid(void){

long __res;

__asm__volatile("int $0x80")

:"=a" (__res)

:"" (__NR_getuid));

__syscall_return(int,__res);

}

程序通过调用宏__NR_getuid得到调用号,放到寄存器eax中,然后执行中断指令,"int $0x80".

第二步:

系统自动进行模式和堆栈切换,并将控制转移到system_call的入口点,在文件entry.s中可以找到system_call的入口点(汇编语言编写)

调用接口函数:

接口函数:

是真正提供给用户编写应用程序的接口,一般以函数库的形式存在,一般在(usr/src/linux-2.0.0/lib/lib***.a)中,在这个函数库中有所有系统 调用接口函数的目标代码,接口函数一般是由汇编语言编写的,主要功能是将系统调用号以及入口参数的地址传递给linux的核心,并使用户态下
的应用程序陷入核心态

(1)检测系统调用号是否合法

(2)保存系统调用号

(3)保存现场S***EALL

(4)保存当前进程的指针到ebx

(5)根据系统调用号查找系统调用表syscall_table,定位到内核函数

第三步:

传递参数,执行返回一个当前进程的uid,然后将得到 的uid保存到eax中

调用RESTORE_ALL宏恢复现场。



参考文献:《linux系统调用的实现技术》 王姝阳 庞丽萍 李胜利 华中理工大学计算机系 1999年

《linux下系统调用原理解析及增加系统调用的方法》 胡盼盼 华中科技大学计算机学院 2007年
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: