杨舒雯 原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”

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

1.用户态、内核态区别

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

  • 在相应的低级别执行状态下,代码的掌控范围会受到限制。

2.中断处理

  • 中断时从用户态转换为内核态的主要方式。

  • 中断发生的两种情况:1.可能是硬件中断,中断服务进程;2.用户态程序调用了系统调用(其中系统调用是一种特殊的中断)。

  • 当从用户态切换到内核态时,必须要保存用户态的寄存器上下文,中断指令会在寄存器上保存一些寄存器的值放入内核堆栈,比如:用户态栈顶地址(ss:esp),标志寄存器(eflags),cs:eip(为了返回的时候popl弹出保存的返回地址)。同时,将相关联的中端服务历程的入口加载到cs:eip,把当前的堆栈段esp也加载到CPU里面。

  • 中断发生之后第一件事就是保存现场;同样,中断处理结束前的最后一件事情就是恢复现场。也就是说,SAVE ALL之后就是内核态了;restore all之后再返回用户态。

  • iret指令与中断信号(包括int指令)发生时的CPU所做的动作恰好相反。

二、系统调用概述和系统调用的三层皮

1.系统调用概述

  • 系统调用的意义:

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

①把用户从底层的硬件编程中解放出来

②极大的提高了系统的安全

③使用户程序具有可移植性

- 操作系统提供的API和系统调用的关系

①应用编程接口(API)和系统调用是不同的。使用API是为了让用户从底层硬件编程中解放出来。

②API只是一个被封装好的函数定义

③系统调用通过软中断向内核发出一个明确的请求

④Libc库定义的一些API引用了封装例程(wrapper routine),唯一目的就是发布系统调用。libc库定义的API使得程序员不用去以汇编代码进行系统调用而是直接以函数调用的形式。

⑤一般每个系统调用对应一个封装例程,库再用这些封装例程定义出给用户的API

⑥API与系统调用不是单一的一对一的关系,也存在多对多的关系。但也有特例,例如一些数学函数没有用到系统调用

⑦大部分封装例程返回一个整数,其值的含义依赖于相应的系统调用

⑧返回值-1在多数情况下表示内核不能满足进程的请求,Libc中定义的errno变量包含特定的出错码

2.系统调用的三层皮

①系统调用的三层皮:xyz,system_call,sys_xyz。也就是:API,中断向量,服务程序。

②详细过程:首先,xyz()函数是系统调用对应的API,这个应用程序编程接口里面封装了一个系统调用,这个系统调用会触发一个int0x80的中断,产生向量为128的编译异常,0x80这个中断向量对应着system_call这个内核代码的起点,这个内核代码里面会有SAVE_ALL,然后执行到sys_xyz()中断服务程序,进入程序里面处理,在中断服务程序执行完之后会ret_from_sys_call,在return的过程中可能会发生进程调度,如果没有进程调度,就会iret,回到用户态接着执行。

3.系统调用的参数传递方法

①内核实现了很多不同的系统调用, 进程必须指明需要哪个系统调用,这需要传递一个名为系统调用号的参数

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

三、 实验

1.实验要求

①选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/syscall_32.tbl

②参考视频中的方式使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

2.库函数API进行24号系统调用

当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数。 在Linux中是通过执行int $0x80来执行系统调用的,这条汇编指令产生向量为128的编程异常。内核实现了很多不同的系统调用,进程指明需要哪个系统调用,把系统调用号作参数传入eax寄存器。下面以linux系统调用getuid为例简单分析一下系统调用过程。

代码:

getuid.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char const *agrv[])
{
uid_t uid;
uid=getuid();
printf("The current user ID:%d\n",uid);
return 0;
}

执行结果:

3.C代码中嵌入汇编代码进行20号系统调用

代码:

执行结果:

四、 总结

我认为系统调用就是内核将常用的用户需要使用底层硬件或特权级操作的相关代码,封装成服务例程,给每个例程一个编号(系统调用号),当用户需要执行相应功能时,进程产生软中断int 0X80,装系统调用号作为参数传入eax寄存器。完成相应的功能。

《Linux内核分析》第四周:扒开系统调用的三层皮的更多相关文章

  1. 20135327郭皓--Linux内核分析第四周 扒开系统调用的三层皮(上)

    Linux内核分析第四周 扒开系统调用的三层皮(上) 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/U ...

  2. LINUX内核分析第四周——扒开系统调用的三层皮

    LINUX内核分析第四周--扒开系统调用的三层皮 李雪琦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...

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

    一.用户态.内核态和中断处理过程 系统调用是用户通过库函数方式:库函数帮我们把系统调用封装起来. 内核态:高级别执行,可以使用特权指令,访问任意的物理地址. 用户态:低级别执行,代码范围受到限制. C ...

  4. Linux内核分析 笔记五 扒开系统调用的三层皮(下) ——by王玥

    (一)给MenuOs增加time和time-asm命令 更新menu代码到最新版 在main函数中增加MenuConfig 增加对应的Ttime和TimeAsm函数 make rootfs (二)使用 ...

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

    实验过程 选择20号系统调用getpid(取得进程识别码) 在网上查询getpid函数的C语言代码以及其嵌入式汇编语句 C语言代码: #include <stdio.h> #include ...

  6. Linux内核设计第四周——扒开系统调用三层皮

    Linux内核设计第四周 ——扒开系统调用三层皮 一.知识点总结 (一).系统调用基础知识 1.用户态和内核态 内核态:在高级别的状态下,代码可以执行特权指令,访问任意的物理地址: 用户态:在相应的低 ...

  7. 《Linux内核分析》第四周 扒开系统调用的“三层皮”

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FOUR( ...

  8. linux 内核 第四周 扒开系统调用的三层皮 上

    姬梦馨 原创作品 http://mooc.study.163.com/course/USTC-1000029000 一.用户态.内核态和中断处理过程 用户通过库函数与系统调用联系起来:库函数帮我们把系 ...

  9. Linux内核分析——第四周学习笔记20135308

    第四周 扒开系统调用的“三层皮” 一.内核.用户态和中断 (一)如何区分用户态.内核态 1.一般现在的CPU有几种不同的指令执行级别 ①在高级别的状态下,代码可以执行特权指令,访问任意的物理地址,这种 ...

  10. LINUX内核分析第四周学习总结——扒开系统调用的“三层皮”

    LINUX内核分析第四周学习总结--扒开系统调用的"三层皮" 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC ...

随机推荐

  1. SDN第4次上机作业

    作业链接 1.建立以下拓扑,并连接上ODL控制器. ODL拓扑界面截图: 安装odl参考链接 2.利用ODL下发流表,使得h3在10s内ping不通h1,10s后恢复. 验证性连通性截图: 将hard ...

  2. 团队作业8-测试与发布(beta阶段)

    小组成员 [组长]金盛昌(201421122043).刘文钊(20142112255).陈笑林(201421122042) 张俊逸(201421122044).陈志建(201421122040).陈金 ...

  3. numpy 的排序

    import numpy as np # 1.快速排序 ''' 1.np.sort(),不改变原先值的顺序,但是在运行时占内存 2.ndarry.sort(),改变原先值的顺序,不占用内存 ''' # ...

  4. 友盟推送SDK集成测试、常见问题以及注意事项总结

    最近为了解决公司APP在一些手机出现的推送问题重新集成了最新版的友盟推送SDK,花费了几天时间终于把集成和测试工作完成,最终在华为,Nexus,三星,小米,HTC,魅族等10多部手机上测试并达到了预想 ...

  5. php请求API接口方法

    thinkphp下直接放入公共函数即可. /** * 通过URL获取页面信息 * @param string $url 地址 * @return string 返回页面信息 */ function g ...

  6. Python高级知识点总结

    一.可迭代对象.迭代器对象和生成器 像list, tuple等这些序列是可以使用for...in ...语句来进行遍历输出的.这是为什么呢?这就需要知道可迭代对象(Iterable).迭代器对象(It ...

  7. oracle中over函数

    1.oracle中按一个字段分组排序后取第一条数据. SELECT * FROM (SELECT ROW_NUMBER() OVER(PARTITION BY 分组字段 ORDER BY 排序字符 D ...

  8. 数据同步canal服务端介绍

    1.下载安装包 canal&github的地址,最权威的学习canal相关知识的地方 https://github.com/alibaba/canal 在下面的wiki列表中找到AdminGu ...

  9. php连接mysql...mysqli和mysql

    mysql_connect()这一系列函数已经不推荐使用了,不安全. <?php $con = mysql_connect('localhost','root','');// 选择连接数据库系统 ...

  10. [SDOI2009]HH的项链 BZOJ1878

    分析: 听说是莫队裸题,很显然,我并不喜欢莫队. 我们可以考虑将询问离线,以右端点排序,之后从1枚举到n,依次树状数组中修改i和last[i],之后当i==询问的右节点时,find一下答案就可以了. ...