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

《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. 张高兴的 .NET Core IoT 入门指南:(二)GPIO 的使用

    什么是 GPIO GPIO 是 General Purpose Input Output 的缩写,即"通用输入输出". Raspberry Pi 有两行 GPIO 引脚, Rasp ...

  2. Sublime2 DocBlocker插件在自动补全注释时输出自定义作者和当前时间等信息

    Sublime在进行前端开发时非常棒,当然也少不了众多的插件支持,DocBlocker是在Sublime平台上开发一款自动补全代码插件,支持JavaScript (including ES6), PH ...

  3. C++虚函数再复习

  4. php 数据集转换树、递归重组节点信息多维数组(转)

    一.将数据集转换成树 /** * 将返回的数据集转换成树 * @param array $list 数据集 * @param string $pk 主键 * @param string $pid 父节 ...

  5. 流式套接字:基于TCP协议的Socket网络编程(案例3)

    案例:在案例1的基础上将传输的字符串换成具体的对象. 客户端代码: package com.yh.SocketObject; import java.io.IOException; import ja ...

  6. Spring(十六)之MVC框架

    MVC 框架教程 Spring web      MVC 框架提供了模型-视图-控制的体系结构和可以用来开发灵活.松散耦合的 web 应用程序的组件.MVC 模式导致了应用程序的不同方面(输入逻辑.业 ...

  7. leetcode55—Jump Game

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  8. E - A Twisty Movement

    A dragon symbolizes wisdom, power and wealth. On Lunar New Year's Day, people model a dragon with ba ...

  9. XML 的4种解析方式

    在上一篇博客中,我们介绍了什么是 XML ,http://www.cnblogs.com/ysocean/p/6901008.html,那么这一篇博客我们介绍如何来解析 XML . 部分文档引用:ht ...

  10. Android导入AS工程

     AS  导入工程 还得 新建工程贴代码