码迷,mamicode.com
首页 > 其他好文 > 详细

系统调用上

时间:2016-05-09 14:19:29      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:

1.用户态、内核态和中断处理过程

1.1 用户态和内核态简介

一般现代CPU都有几种不同的指令执行级别。在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别就对应着内核态;而在相应的低级别执行状态下,代码的掌控范围会受到限制,只能在对应级别允许的范围内活动,这种CPU执行级别就对应着用户态

例如:intel*86CPU有4种不同的执行级别0,1,2,3,Linux只使用了其中的0级和3级分别表示内核态和用户态。

1.2 区分用户态和内核态

显著的区分方法是看cs:eip,在内核态时,cs:eip可以是任意的值。

一般来讲在linux中,地址空间(逻辑地址)是一个显著的标志:0xc0000000以上的地址空间只能在内核态下访问,0x00000000——0xbfffffff的地址空间可在两种状态下访问。

1.3 中断处理

1.3.1 用户态进入内核态

用户态进入内核态的方式:中断、调用系统调用。

中断处理是从用户态进入内核态主要的方式,系统调用是一种特殊的中断。

1.3.2 寄存器的上下切换

用户态进入内核态时会发生寄存器的上下切换,要保存用户态的寄存器上下文。

中断/int指令会在堆栈上保存一些寄存器的值,如用户态栈顶地址、当前的状态字、当时的es:eip的值等。

中断发生后的第一件事就是保存现场(进入中断程序,保存需要用到的寄存器的数据),中断处理程序结束前最后一件事就是恢复现场(退出中断程序,恢复、保存寄存器的数据)。

1.3.2 中断处理的完整过程

//系统调用,保存cs:eip,当前堆栈段、栈顶、标志寄存器到内核堆栈,同时加载中断信号或系统调用,相关联的中断服务例程、ss:eip

interrupt(ex:int 0x80)-save cs:eip/ss:esp/eflags(current)to kernel stack,then load cs:eip(entry of specific ISR)and ss:eip(point to kernel stack).

//完成上述步骤之后,当前CPU在执行下一条指令,就在执行中断处理程序的入口,对堆栈的操作不再是用户态的堆栈,开始操作内核态堆栈

save_all

//内核代码,完成中断服务,发生进程调度。如果完成中断服务,没有发生进程调度,就会返回到原来的状态;如果发生进程调度,当前的状态

//就会暂时保存

restore_all

iret-pop cs:eip/ss:eip/eflags from kernel stack

2.系统调用概述

2.1系统调用的意义

系统调用:操作系统为用户态进程与硬件设备进行交互提供了一组接口。

把用户从底层的硬件编程中解放出来;极大的提高了系统安全性;使用户程序具有可移植性。

2.2应用程序编程接口(application program inteface,API)

API和系统调用

  • API只是一个函数定义;
  • 系统调用通过软中断向内核发出一个明确的请求;
  • 不是每个API对应一个特定的系统调用。如API可能直接提供用户态的服务(如,一些数学函数);一个单独的API可能调用几个系统调用;不同的API可能调用了同一个系统调用。
  • 返回值。大部分封装例程返回一个整数,其含义依赖与相应的系统调用;-1在多数情况下表示内核不能满足进程的请求。

图解:

技术分享

函数xyz()是系统调用对应的API,API中封装了系统调用,会触发一个int 0x80的中断,0x80这个中断向量对应着system_call这个内核代码的入口起点。

2.3获取当前系统时间

#include <stdio.h>
#include <time.h>

int main(){
    time_t tt;
    struct tm *t;
    //tt=time(NULL);
    asm volatile(
        "mov $0,%%ebx\n\t"
        "mov $0xd,%%eax\n\t"
        "int $0x80\n\t"
        "mov %%eax,%0\n\t"
        : "=m" (tt)
    );
    t=localtime(&tt);
    printf("%d,%d,%d",t->tm_year+1900,t->tm_mon,t->tm_wday);
    return 0;
}

分析嵌入式汇编代码:

首先ebx清0(系统调用传递的第一个参数使用ebx,这里是NULL),然后0xd放在eax中(eax是传递系统调用号,这里time是0xd(13)),

返回值通过eax寄存器返回,eax放在%0即tt这个变量。

系统调用上

标签:

原文地址:http://www.cnblogs.com/boyiliushui/p/5473601.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!