使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
2016-03-19 20:35
369 查看
刘森林
原创作品转载请注明出处《Linux内核分析》MOOC课程
实验截图
time的系统调用号为13,获取当前的系统时间。
编写两段代码,分别使用库函数API和C代码中嵌入汇编代码,源码如下:
time.c(使用库函数API方式)
time-asm.c(使用C代码中嵌入汇编代码方式):
运行结果如下
1.执行用户程序(如:time)
2. 取得系统调用号并执行int $0x80产生中断。
3.进行地址空间的转换和堆栈的切换,执行SAVE_ALL。(进行内核模式)
4. 进行中断处理,根据系统调用表调用内核函数。
5. 执行内核函数。
6. 执行RESTORE_ALL并返回用户模式
在i386体系中,Linux的系统调用是通过调用软中断指令“int 0x80”使进程从用户态进入内核态的,这个过程也叫做“trap”。当系统调用接口调用软中断指令“int 0x80”时,这个指令会发生一个中断向量码为128的中断请求,并在中断响应过程中将进程由用户态切换为内核态。
因为Linux只允许系统调用接口使用128这一个软中断向量,这也就意味着所有的系统调用接口必须共享这一个中断通道,并在同一个中断服务例程中调用不同的内核服务例程,所以,系统调用接口除了要引发“int 0x80”软中断之外,为了进人内核后能调用不同的内核服务例程,还要提供识别内核服务例程的参数,这个参数叫做“系统调用号”。也就是说,所有可为进程提供服务的内核服务例程都应具有一个唯一的系统调用号。当然,系统调用接口还应为内核服务例程准各必要的参数。
原创作品转载请注明出处《Linux内核分析》MOOC课程
实验目的
使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用,理解系统调用的工作机制。实验过程
这一次的实验使用的是我的Linux虚拟机Ubuntu 14.04.2 LTS 64bit实验截图
time的系统调用号为13,获取当前的系统时间。
编写两段代码,分别使用库函数API和C代码中嵌入汇编代码,源码如下:
time.c(使用库函数API方式)
#include<stdio.h> #include<time.h> int main(){ time_t tt; struct tm *ptr; tt=time(NULL); ptr=localtime(&tt); printf("second:%d\n",ptr->tm_sec); printf("minute:%d\n",ptr->tm_min); printf("hour:%d\n",ptr->tm_hour); printf("mday:%d\n",ptr->tm_mday); printf("month:%d\n",ptr->tm_mon+1); printf("year:%d\n",ptr->tm_year+1900); return 0; }
time-asm.c(使用C代码中嵌入汇编代码方式):
#include<stdio.h> #include<time.h> int main(){ time_t tt; struct tm *ptr; asm volatile( "mov $0,%%ebx\n\t"//将ebx寄存器清零 4000 "mov $0xd,%%eax\n\t"//time的系统调用号为0x13,赋值给eax "int $0x80\n\t"//通过0x80中断向量,执行系统调用 "mov %%eax,%0\n\t"// :"=m"(tt)//输出tt ); ptr=localtime(&tt); printf("second:%d\n",ptr->tm_sec); printf("minute:%d\n",ptr->tm_min); printf("hour:%d\n",ptr->tm_hour); printf("mday:%d\n",ptr->tm_mday); printf("month:%d\n",ptr->tm_mon+1); printf("year:%d\n",ptr->tm_year+1900); return 0; }
运行结果如下
Linux的系统调用机制分析
整个系统调用的过程可以总结如下:1.执行用户程序(如:time)
2. 取得系统调用号并执行int $0x80产生中断。
3.进行地址空间的转换和堆栈的切换,执行SAVE_ALL。(进行内核模式)
4. 进行中断处理,根据系统调用表调用内核函数。
5. 执行内核函数。
6. 执行RESTORE_ALL并返回用户模式
在i386体系中,Linux的系统调用是通过调用软中断指令“int 0x80”使进程从用户态进入内核态的,这个过程也叫做“trap”。当系统调用接口调用软中断指令“int 0x80”时,这个指令会发生一个中断向量码为128的中断请求,并在中断响应过程中将进程由用户态切换为内核态。
因为Linux只允许系统调用接口使用128这一个软中断向量,这也就意味着所有的系统调用接口必须共享这一个中断通道,并在同一个中断服务例程中调用不同的内核服务例程,所以,系统调用接口除了要引发“int 0x80”软中断之外,为了进人内核后能调用不同的内核服务例程,还要提供识别内核服务例程的参数,这个参数叫做“系统调用号”。也就是说,所有可为进程提供服务的内核服务例程都应具有一个唯一的系统调用号。当然,系统调用接口还应为内核服务例程准各必要的参数。
两种方式调用的分析
用API进行系统调用,实际是在各个API系统调用函数中封装了系统调用接口,用户使用API系统调用函数时,则跳转向该接口,从而进入内核态;而直接用嵌入式汇编进行系统调用则是直接用汇编代码启动中断向量,从而进入内核态。相关文章推荐
- MyEclipse xml 手动添加 dtd
- 搜狐Java开发实习生笔试题
- Java中Arraylist可以像链表一样不需初始声明大小而增长的原因
- struts2上传文件(一) 表单设置
- LeetCode – Two Sum (Java) —题解
- c++第二次上机-2
- JavaWeb开发之十四:JavaWeb两种开发模式
- JavaWeb开发之十三:Javabean
- Java中@Override的作用
- Leetcode 第一题 Two Sum java代码
- Java面对对象入门
- C++将分配值8到变量
- C++服务器(五):pthread多线程编程
- eclipse的两个不同程序并排摆放,便于查看
- 关于c++中stack、queue和priority_queue的介绍
- c++四种类型转换
- Wireshark使用drcom_2011.lua插件协助分析drcom协议
- 我自己使用github上传小demo的常用步骤
- python decorator装饰器
- Java基础之异常篇