Linux内核分析04

扒开系统调用的三层皮(上)

一,用户态、内核态和中断

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

用户态和内核态的区分

内核态:代码可以执行特权指令,访问任意的物理地址,CPU的这种执行级别就对应着~

相对的用户态就对应着低级别的执行状态就是用户态,代码所掌控的范围有限。

至于为什么会划分权限,因为操作系统的发展,防止程序员写的代码造成系统运转的崩溃

划分为0、1、2、3四个级别 内核态为0,用户态则为3.

进程地址空间里所提到的地址指的是逻辑地址而不是物理地址。

中断处理是从用户态进入内核态的主要方式。

从用户态切换到内核态时必须保存用户态的上下文在寄存器里,int指令会在堆栈上保存一些寄存器的值,

系统调用只是一种特殊的中断。

中断后发生的第一件事就是保护现场,save all,例如:状态字、栈顶地址、cs:eip的值

最后一件事是恢复现场。

二,系统调用

应用程序编程接口(API)和系统调用是不同的。

API只是一个函数定义,而系统调用通过软中断向系统内核提出明确请求。

一般情况一个系统调用对应一个封装例程,函数库再用这些封装例程定义出方便程序员使用的函数。

-1表示内核不能满足请求。

系统调用的三层皮:API xyz、中断向量  system_call、 中断服务  sys_xyz。  

系统调用号将xyz和sys_xyz关联起来,指名那个系统调用,用eax%来传递。

传递参数方法是 每个参数的长度不能超过寄存器长度,也就是说不能超过六个,把寄存器当做一个指针,在内核传递。并没有看到超过六个怎么办。。

,使用库函数API和C代码中嵌入汇编代码触发同一个系统调用

C语言程序中嵌入式汇编代码的写法:

_asm_(

  汇编代码:

  输出部分:

  输入部分:

  );

前面的笔记里也有提到过的。

用“=m”写到内存里去,不是放在寄存器了。

常用嵌入汇编语言限定符:a、r、=等等。

用汇编方式触发系统调用获取当前时间。

系统调用的第一个参数用ebx%,一般是NULL。

系统调用的返回值用eax存储,和普通函数一样。

四,实验

我使用第20号调用,getpid按照步骤来C语言编译运行:

汇编编译运行:

五,疑惑

1、为什么在保存的时候不保存中断向量?

2、超过六位怎么办。。。。

原文地址:https://www.cnblogs.com/KG35/p/5297548.html