linux内核分析 第四周 扒开系统调用的三层皮(上)

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

系统调用是用户通过库函数方式:库函数帮我们把系统调用封装起来。

内核态:高级别执行,可以使用特权指令,访问任意的物理地址。

用户态:低级别执行,代码范围受到限制。

CS寄存器的最低两位表明了当前代码的特权级。

在linux中,0xc0000000以上的地址空间只能在内核态下访问,0x00000000-0xbfffffff的地址空间两种状态下都可以使用。(逻辑地址)

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

从用户态进入内核态:必须保存用户态的寄存器上下文

中断/int指令在堆栈上保存寄存器的值:用户态/内核态栈顶地址(ss:esp)、状态字(eflags)、cs:eip值(内核态时指向中断服务程序入口)

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

中断发生后第一件事就是保存现场

中断处理结束前最后一件事是恢复现场

三、系统调用概述

1、系统调用的意义

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

用户不管硬件编程

提高系统安全性

用户程序可移植

2、API和系统调用

API:应用编程接口,是一个函数定义

系统调用:通过软中断向内核发出明确请求

Libc库定义的一些API引用了封装例程(唯一目的就是发布系统调用)

一般每个系统调用对应一个封装例程

库用封装例程定义出给用户的API

不是每个API都对应一个特定的系统调用

API可直接提供用户态服务,如数学函数

一个API可调用几个系统调用

不同API可调用同一系统调用

3、返回值:

封装例程返回一个整数,含义依赖与相应系统调用

-1表示内核不能满足进程的要求

Libc定义的errno变量包含特定出错码

四、系统调用三层皮:

API(xyz)

中断向量(system_call)

中断服务程序(sys_xyz)

用户态进程调用系统调用时,CPU切换到内核态执行内核函数(Linux中通过执行int $128来执行系统调用,产生向量为128的编程异常)

五、传参:

进程指明需要哪个系统调用,传递系统调用号,使用eax传递

系统调用号将xyz与sys_xyz关联起来

system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即系统调用号。

寄存器传递参数的限制:

每个参数长度不能超过寄存器长度即32位

在系统调用号eax之外,个数不能超过6个

超过6的话:某个寄存器中存储指针,指针会指向一个内存空间,存储参数

系统调用传递第一个参数使用ebx。

六、实验

1.选择20号系统调用,getpid来获取当前进程的pid

2.实验内容:

使用库函数API方式:

使用C代码中嵌入汇编代码方式:

posted @ 2016-03-20 21:51  20125221银雪纯  Views(220)  Comments(0Edit  收藏  举报