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

《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. Google常用脚本

    1.Tampermonkey 可下载常用脚本:https://greasyfork.org/zh-CN 2.常用FQSetupVPN 3.百度药丸屏蔽广告 4.百度文档可粘贴,下载 5.VIP视频可看

  2. Learn Algorithms With Javascript - 基于 Js 进行算法学习

    基于 javascript 学习并实现常用的经典算法,欢迎对算法和数学感兴趣的 Js 开发者参与,一起学习共同进步. 算法实现 排序 插入排序 sort/lib/insertion-sort.js 希 ...

  3. gcd以及exgcd入门讲解

    gcd就是最大公约数,gcd(x, y)一般用(x, y)表示.与此相对的是lcm,最小公倍数,lcm(x, y)一般用[x, y]表示. 人人都知道:lcm(x, y) = x * y / gcd( ...

  4. Flask 入门一( flask 框架和 flask-script 库)

    Flask 入门一( flask 框架 和 flask-script 库) 一.Flask框架: 1.简介 Flask是一个非常小的Python Web框架,被称为微型框架:只提供了一个稳健的核心,其 ...

  5. Mike的农场 BZOJ4177

    分析: 最小割,不选则割的建模题...(然而一开始我当成了费用流,简直丧心病狂...最后想到了最小割...) 对于条件一,直接建一条双向边就可以了,并且不计入sum中,因为这是作为费用的存在,让它跑出 ...

  6. 20155224 聂小益 《基于Arm实验箱的接口测试和应用》 课程设计报告

    一.设计方案及可行性分析 熟悉 Linux 开发环境 多线程应用程序设计 串行端口程序设计 中断实验 二.详细设计思路 1. 熟悉 Linux 开发环境 建立工作目录: 在终端输入代码建立工作目录 [ ...

  7. 20155306 白皎 0day漏洞——漏洞的复现

    一.Ubuntu16.04 (CVE-2017-16995) 1.漏洞概述 Ubuntu最新版本16.04存在本地提权漏洞,该漏洞存在于Linux内核带有的eBPF bpf(2)系统调用中,当用户提供 ...

  8. EZ 2018 04 06 NOIP2018 模拟赛(七)

    我是链接 这次是真的惨,码了将近2hours的可持久化线段树炸掉了! 而且本地拍了一万年也没发现哪里炸了. T1 压位的入门题,话说这道题能拿个99分就可以了(100分要FFT) 对于暴力,就是暴力找 ...

  9. mount状态下表空间情报试验

    SQL> shutdown immediate;Database closed.Database dismounted.ORACLE instance shut down.SQL> sta ...

  10. stl源码剖析 详细学习笔记 RB_tree (2)

    //---------------------------15/03/22---------------------------- //一直好奇KeyOfValue是什么,查了下就是一个和仿函数差不多 ...