您的位置:首页 > 运维架构 > Linux

linux中的系统调用机制

2017-03-15 11:17 134 查看
张建帮 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

关于linux的系统调用,以下这张图片可以解释得比较清楚:



这幅图片以fork()函数为例,详细阐述了系统调用的具体的步骤与流程:

在源文件中使用的
fork()
函数会调用函数库中的
fork()
函数

函数库中的
fork()
会将
sys_fork
的系统调用号
2
保存在
eax
寄存器中,然后调用
int $0x80
指令自陷,进入内核态

系统根据立即数
$0x80
,到IDT(Interrupt Descriptor Table,中断描述符表)中找到对应的中断处理程序的入口地址

开始执行中断处理程序

中断处理程序根据
eax
寄存器中存储的系统调用号,到
SCT
(Systerm call table,系统调用表)中找到
sys_fork()
的入口地址

执行
sys_fork
系统调用

明白了整个系统调用的流程后,我们就可以通过嵌入式汇编直接调用想调用的系统调用了,具体流程如下:

查询相应的系统调用号

将系统调用号保存到
eax
寄存器中

通过
int $0x80
指令自陷

函数调用完成,自动将结果(返回值)保存在
eax
寄存器中

eax
寄存器的内容进行输出

整体的流程相当于把函数库中的工作实现了一遍。

现在以
getpid
为例,分别用C函数库和嵌入式汇编(查看嵌入式汇编相关知识)实现其系统调用:

(getpid的系统调用号是
20
点这里查看完整的系统调用列表

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("pid is %d\n",getpid());

int pidAsm = 0;
asm volatile(
"mov $0, %%ebx\n\t"   //系统调用第一个参数,清零,不清零好像也没影响
"mov $20, %%eax\n\t"  //保存系统调用号
"int $0x80\n\t"    //自陷
"mov %%eax, %0\n\t"  //将结果保存到变量 pidAsm中
: "=m"(pidAsm)
);
printf("using asm,pid is %d\n", pidAsm);
}


运行结果如下:



可以看到,两种方式得到的结果是一样的,这也印证了我们的猜想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 linux 系统调用