第4章 系统调用的三层机制(上)

1  用户态、内核态和中断

大多数程序员在写程序时很难离开系统调用,与系统调用打交道的方式是通过库函数的方式,库函数用来把系统调用给封装起来。

计算机的硬件资源是有限的,为了减少有限资源的访问和使用冲突,CPU和操作系统必须提供一些机制对用户程序进行权限划分。于是就有了用户态和内核态,在高的执行级别下,代码可以执行特权指令,访问任意的物理内存,这时CPU的执行级别对应的就是内核态,对所有的指令包括特权指令都可以执行。相应的,在用户态(低级别指令),代码能够掌握的范围会受到限制。

Intel x86 CPU有4种不同的执行级别,分别是0、1、2、3,数字越小,特权越高。Linux操作系统中只是采用了其中的0和3两个特权级别,分别对应内核态和用户态。

用户态和内核态很显著的区分方法就是CS:EIP的指向范围,在内核态时,CS:EIP的值可以是任意的地址,而在用户态时,该值是受限制的。

系统调用也是一种中断(中断处理是从用户态进入内核态的主要方式)。一般来说,进入内核态是由中断触发的,可能是硬件中断,也可能是用户态程序执行的过程中,调用了一个系统调用,陷入了内核态,叫作Trap(系统调用只是特殊的中断)。

当用户态切换到内核态时,就要把用户态寄存器上下文保存起来,同时要把内核态的寄存器的值放到当前CPU中。int指令触发中断机制会在堆栈上保存一些寄存器的值,会保存用户态栈顶地址、当时的状态字、当时的CS:EIP的值。同时会将内核态的栈顶地址、内核态的状态字放入CPU对应的寄存器,并且CS:EIP寄存器的值会指向中断处理程序的入口,对于系统调用来讲是指向system_call。

中断的处理过程:Linux下系统调用通过int 0x80中断完成,中断保存了用户态CS:EIP的值,以及当前的堆栈段寄存器的栈顶,将EFLAGS寄存器的当前的值保存到内核堆栈里,同时把当前的中断信号或者是系统调用的中断服务程序的入口加载到CS:EIP里,把当前的堆栈段SS:ESP也加载到CPU里,这些都是由中断信号或者是int指令来完成的。完成后,当前CPU在执行下一条指令时就已经开始执行中断处理程序的入口了,这时对堆栈的操作已经是内核堆栈操作了,之前的SAVE_ALL就是内核代码,完成中断服务,发生进程调度,就直接restore_all恢复中断现场,然后iret返回到原来的状态;如果发生了进程调度,当前的这些状态都会暂时地保存在系统和内核堆栈里,当下一次发生进程调度时,就会接着把restore_all和iret执行完,这就是整个的中断处理过程。

2  系统调用概述

系统调用是通过软中断(trap的方式)向内核发出了中断请求,int指令的执行就会触发一个中断请求。

一般每个系统调用对应一个系统调用的封装例程,函数库再用这些封装例程定义出给程序员调用的API,这样把系统调用最终封装成方便程序员使用的库函数。

libc提供的API可能直接提供一些用户态的服务,并不需要通过系统调用与内核打交道,比如一些数学函数等,但涉及与内核空间进行交互的API内部会封装系统调用。一个API可能只对应一个系统调用,也可能内部由多个系统调用实现,一个系统调用也可能被多个API调用。不涉及与内核进行交互的API内部不会封装系统调用,比如用于求绝对值的数学函数abs()。

对于返回值,大部分系统调用的封装例程返回一个整数,其值的含义依赖于对应的系统调用,返回值-1在多数情况下表示内核不能满足进程的请求,libc中进一步定义的errno变量包含特定的出错码。

总而言之,系统调用的3层机制为:API、中断向量、中断服务程序。

当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个system_call和系统调用内核函数。在Linux中通过执行int $0x80来触发系统调用的执行,这条汇编指令产生中断向量为128的编程异常。进入内核后,开始执行中断向量128对应的中断服务程序system_call,Linux操作系统大概有200个系统调用,在这里内核通过给每个系统调用一个编号来区分,即系统调用号,将API函数xyz()和系统调用内核函数sys_xyz()关联起来了。内核实现了很多不同的系统调用,用户态进程必须指明需要哪个系统调用,这就需要使用EAX寄存器传递一个名为系统调用号的参数。除了系统调用号外,系统调用也可能需要传递参数,普通函数调用是通过将参数压栈的方式传递的。系统调用从用户态切换到内核态,在两种执行模式下使用的是不同的堆栈,即进程的用户态和进程的内核态堆栈,传递参数方法无法通过参数压栈的方式,而是通过比较特殊的寄存器传递参数的方式。除了EAX用于传递系统调用号外,参数按顺序赋值给EBX、ECX、EDX、ESI、EDI、EBP,参数的个数不能超过6个,即上述6个寄存器。如果超过6个就把某一个寄存器作为指针指向内存,这样就可以通过内存来传递更多的参数。

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

      编写一个time.c程序:

      使用库函数API触发一个系统调用

       

       

 C代码中嵌入汇编代码触发一个系统调用:

含有两个参数的系统调用范例

在这里我们实现将hello.c文件重新命名newhello.c,返回值为0表示修改成功。

使用库函数API触发rename系统调用,系统调用rename的功能是给一个文件重命名,如下图所示:

接下来就是嵌入式汇编代码触发rename系统调用,如下图所示:

在这里出现了一个问题:我用“gcc rename_asm.c”命令编译时出现了错误“ Error:unsupported instruction 'mov' ”,然后我使用“ gcc rename_asm.c -o rename_asm -m32 ”命令就编译成功,这是因为32位汇编代码对应的是movl。

然后这段汇编代码的意思为:把系统调用号38(16进制是0x26)存入EAX寄存器,将oldname存入EBX寄存器,将newname存入ECX寄存器,通过执行int $0x80来执行系统调用陷入内核态。system_call根据传入的系统调用号在系统调用列表中查找到对应的系统调用内核函数,然后根据EBX寄存器和ECX寄存器中保存的参数调用内核函数sys_rename,执行完后将执行结果存放到EAX寄存器中,将EAX寄存器的值传给ret。

接下来将“=a”换成“=m”,得到如下图所示结果:

可以看到hello.c确实变成了newhello.c,却显示没有修改成功。hello.c变成newhello.c,表示确实执行了sys_rename,返回值0保存在EAX寄存器中。显示失败是指ret不等于0。

通用的触发系统调用的库函数syscall

如果libc没有提供对某个系统调用的封装,就无法通过API方法来调用内核函数,或者说内核增加了一个新的系统调用,但libc函数库的版本没有及时更新为其编写API函数,这种情况下我们就可以利用libc提供的syscall函数直接调用,函数原型为:extern long int syscall(long int sysno,...) _THROW,其中sysno是系统调用号,“...”是系统调用所带的参数。如下图所示:

这里将SYS_rename改为38也可以实现。

4  总结

      在本次实验中,我初步了解到了一些关于系统调用的工作机制,比如系统调用可以用API函数直接调用或者在C语言中嵌入汇编代码来进行调用,但是两者都需要使用系统调用号,不同的是API函数已经把系统调用号封装起来了,与内核系统调用形成了映射关系。

     

       

2019-2020-5 20199317《Linux内核原理与分析》第五周作业的更多相关文章

  1. 2019-2020-1 20199329《Linux内核原理与分析》第九周作业

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

  2. 2019-2020-1 20199329《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...

  3. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  4. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  5. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  6. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  7. 2019-2020-1 20209313《Linux内核原理与分析》第二周作业

    2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  10. 2018-2019-1 20189221《Linux内核原理与分析》第二周作业

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

随机推荐

  1. [Hadoop]Hive-1.2.x安装配置+Mysql安装

    HIve的元数据存储在mysql中,需要配置与MySQL建立连接,除了安装MySQL外还要安装连接的jar包:mysql-connector-java-5.1.47.tar.gz   安装环境:Cen ...

  2. P3052 [USACO12MAR]摩天大楼里的奶牛(迭代加深搜索)

    (已经一句话了) 第一反应:暴力 第二反应:朴素算法过不去 第三反应:没法折半暴搜(没法统计答案) 所以,歪歪了一个类似贪心刷表的方法,过了这道题. 首先,如果爆搜的话会有几个状态: 当前牛 当前几个 ...

  3. Xshell和Xftp 安装及使用

    Xshell Xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议.Xshell 通过互联网到远程主机的安全连接以 ...

  4. IntelliJ IDEA自动部署项目至远程服务器与传统部署项目至远程服务器的区别

    每次开发Java项目时,对于所有Java开发人员来说,最枯燥的不是修改代码,而是实时将自己的代码上传至远程服务器,进行测试或者部署,本人最初开发也是这样,通过使用Xshell 5,WinSCP等工具对 ...

  5. html5 textarea 写入换行的方法

    html5 textarea 写入换行的方法<pre> <textarea id="fwe" class="selmiao" cols=&qu ...

  6. 【北京/上海/南京】【部门直推】【可查询】【实习&社招】字节跳动数据平台前端内推

    [北京/上海/南京][部门直推][可查询][实习&社招]字节跳动数据平台前端内推 重要信息,写在前面  [投递邮箱]chengxinsong@bytedance.com [微信扫码] 2019 ...

  7. 数据分析之路 第一篇 numpy

    第一篇 numpy 1.N维数组对象 :ndarray在Python中既然有了列表类型,为啥还要整个数组对象(类型)?那是因为:1.数组对象可以除去元素间运算所需要的循环,使得一维向量更像单个数据2. ...

  8. 201871010114-李岩松《面向对象程序设计(java)》第十周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  9. [剑指offer]删除链表中重复的结点(把重复的都删掉,1个不留)

    ①题目 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后为 ...

  10. C语言|博客作业01

    2.1你对计算机科学与技术的了解是怎样? 一开始,我并不知道计科和软件的区别,甚至以为这是一种专业的两种叫法.进了大学之后,才一下子懂了,计科就是计科,它和软件虽有相同之处,但是终究是不一样的.计科涉 ...