扒开系统调用的三层皮?(上)

第4章的基础知识

  • Linux系统调用的三层机制:xyz()(API函数)、system_call(系统调用处理入口) 、 sys_xyz()(系统调用内核处理函数)。
  • 32位的X86机器上在用户态的时候只能访问0x00000000—0xbfffffff的地址空间,而在内核态下可以访问所有的地址空间。
  • 中断,系统调用是最常用的两种方式,从用户态切换到内核态。
  • int指令触发中断机制会在堆栈上保存一些寄存器的值,会保存用户态栈顶地址,当时的状态字,当时的CS:EIP的值。
  • 中断发生后的第一件事就是保存现场,中断结束的最后一件事就是恢复现场。
  • 系统调用的意义可以把用户从底层的硬件编程中解放出来,极大的提高了系统的安全性,使用户程序具有可移植性。
  • API(应用程序编程接口)是函数定义,一个API可以对应多个系统调用,他们之间是多对多的关系。
  • 使用EAX寄存器传递一个名为系统调用号的参数。
  • Linux操作系统中采用了0和3两个特权级别,分别对应内核态和用户态。
  • 在Linux中,系统调用是用户空间访问内核的惟一手段;除异常和中断外,它们是内核惟一的合法入口。   而kernel留给用户层的接口其实就只有一个:软中断(int 0x80)。用户态通过它来陷入内核态,完成系统调用。为了方便使用,kernel与用户层之间又增加了API与一些库(例如libc库)来封装这一过程。因此,目前的资料里大部分都写,调用一个系统调用有三种方法:
           (1)通过 glibc 提供的库函数
           (2)使用 syscall 函数直接调用
           (3)通过 int 0x80指令陷入
  • API/libc与系统调用的关系:既然API与libc对软中断进行了封装,那我们先一起看看它们之间的具体关系。一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程。这点很重要,因为应用程序使用的这种编程接口实际上并不需要和内核提供的系统调用一一对应。一个API定义了一组应用程序使用的编程接口。从程序员的角度看,系统调用无关紧要,他们只需要跟API打交道就可以了。相反,内核只跟系统调用打交道;库函数及应用程序是怎么使用系统调用不是内核所关心的。

系统调用实现机制

与调用函数一样,系统调用也需要输入输出参数。每个系统调用至少有一个参数,即系统调用号(由eax传递),其他参数依次由ebx、ecx、edx、esi、edi、ebp传入。 由于使用寄存器传递参数,因此对参数的长度做了限制:
(1)每个参数的长度不能超过寄存器的长度,即32位
(2)在系统调用号(eax)之外,参数的个数不能超过6个(ebx、ecx、edx、esi、edi、ebp)如果超过六个,可以传入一个地址,地址所在地存放多个参数
系统调用的三个层次依次是:xyz函数(API)、system_ call(中断向量)和 sys_ xyz(中断服务程序)。

触发一个系统调用的三种方式

1.API函数的方式
首先我选取的是20号的getpid系统调用

编译的结果如下:

2.嵌入式汇编方式

编译运行完的结果

3.调用库函数syscall

编译完运行的结果

4.用gdb进行调试看API的调用是否就是像我们之前分析的对系统调用的封装那样执行的
在getpid处设置断点,运行到断点处。

使用ni命令,对汇编指令逐条运行,前面的清理寄存器的值此处先不讨论,直接一直ni运行到传递系统调用号处(箭头所指的为下一条将要运行的指令, 利用info r命令来查看当前寄存器的值,系统调用号还未传入,eax还为0)。

ni一下,再次查看,发现系统调用号已经传入,确实是利用eax的。

再ni一下,此时该系统调用的实际工作已经完成了,结果(也就是pid)保存在eax中。

实验分析

  • getpid是一种函数,功能是取得进程识别码。
  • 函数原型:旧的原型为pid_t getpid(void);,推荐使用int _getpid( void );这种形式。注意,函数名第一个字符是下划线。
  • 函数说明:getpid函数用来取得目前进程的进程ID,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。
  • 返回值:目前进程的进程ID。
  • 在Linux系统中是通过激活0x80中断来触发系统调用的,需要调用的系统调用号实现赋值给eax存储器,如果有传入参数可赋值给ebx寄存器,如果多于1个则按顺序赋值给ebx、ecx、edx、esi、edi、ebp,如果超过6个则通过指针变量指向另一片堆栈区,如果无参数传入则赋值为0。
    汇编代码的分析

#include <stdio.h>
#include<unistd.h>
int main()
{pid_t pid;asm volatile("movl $0,%%ebx\n\t"//将ebx寄存器清零,系统调用传递第一个参数使用ebx,这里是null"movl $0x14,%%eax\n\t"//将0xd放入eax中,0x14为20,传递系统调用号20"int $0x80\n\t""movl %%eax,$0\n\t"//通过eax这个寄存器返回系统调用值,和普通函数一样:"=m"(pid));printf("this process's pid is : %u\n",pid);return 0;
}

遇到的问题
1.我最开始在做书上给的38号系统调用的例子的时候,出现了下面的问题

后面再网上搜索资料可以得知是因为在64位系统下去编译32位的目标文件,这样是非法的。必须用”-m32”强制用32位ABI去编译,即可编译通过。

2.我在改写syscall函数的的时候,出现了下面的问题

最后发现是因为缺少必要的头文件,添加上 1 #include <unistd.h>2 #include <sys/syscall.h>3 #include <sys/types.h>即可

本章总结

  • 在Linux中我们可以通过三种方式也进行系统的调用分为:API方式,C代码中嵌入式汇编语言,和库函数syscall。API方法实现系统调用实现非常便捷,只需知道函数原型即可。
  • 经过这次实验,我们可以看到:
          (1)要查看系统资源(如pid等),只有处于内核态(0级)的时候才可以。
           (2)用户要从用户态(3级)切换到内核态(0级),就要通过软中断(int 0x80)来进行系统调用。
           (3)通过eax传递系统调用号,然后由system_call交给system_service完成工作。
           (4)system_service完成工作后,结果又由eax传递给用户态堆栈。
    我对API系统调用的理解:
  • 总之用户调用API函数,系统调用号和参数保存到 eax,ebx ,等寄存器中,通过 0x80 中断向量触发中断陷入内核态,中断服务程序根据系统调用号调用并执行对应的系统调用函数,执行完毕后将结果存放的 eax 中并返回给程序,程序返回用户态。

转载于:https://www.cnblogs.com/yuchao123/p/9917955.html

20189220 余超《Linux内核原理与分析》第五周作业相关推荐

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

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

  2. 2022-2023-1 20222809《Linux内核原理与分析》第一周作业

    Linux内核原理与分析第一周作业 配置环境 1.参考Linux(Ubuntu)系统安装图文教程中第二种借助virtualbox成功配置Ubuntu环境 2.升级更新软件包 可以通过调节分辨率和虚拟机 ...

  3. 实验楼 linux内核原理与分析,《Linux内核原理与分析》第一周作业 20189210

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

  4. 20189220 余超《Linux内核原理与分析》第一周作业

    实验一 Linux系统简介 通过实验一主要是学习到了Linux 的历史简介,linux与windows之间的区别,主要是免费和收费,软件和支持,安全性,使用习惯,可制定性,应用范畴等.linux具有稳 ...

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

    反汇编一个简单的C程序 1.实验要求 使用: gcc –S –o test.s test.c -m32 命令编译成汇编代码,对汇编代码进行分析总结.其中test.c的具体内容如下: int g(int ...

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

    进程调度的时机 进程调度时机就是内核调用schedule函数的时机.当内核即将返回用户空间时,内核会检查need_resched标志是否设置.如果设置,则调用schedule函数,此时是从中断(或者异 ...

  7. 2021-2022-1 20212820《Linux内核原理与分析》第一周作业

    声明:本文是基于Linux 基础入门_Linux - 蓝桥云课 (lanqiao.cn)这门课学习所写的课程笔记. 实验1 Linux系统简介 Linux主要包括是系统调用和内核两部分 Linux与W ...

  8. 20189220 余超《Linux内核原理与分析》第二周作业

    计算机如何工作的 一.存储程序计算机工作模型 冯诺依曼体系结构:核心思想为存储程序计算机.两个层面: (1)硬件的角度(计算机主板):一个CPU,一块内存,之间有总线连接.CPU内部有一个IP计算器, ...

  9. 20189220 余超《Linux内核原理与分析》第九周作业

    理解进程调度时机跟踪分析进程调度与进程切换的过程 本章的基础知识总结 一般来说,进程调度分为三种类型:中断处理过程(包括时钟中断.I/O 中断.系统调用和异常)中,直接调用schedule,或者返回用 ...

  10. 2018-2019-1 20189201 《LInux内核原理与分析》第九周作业

    那一天我二十一岁,在我一生的黄金时代.我有好多奢望.我想爱,想吃,还想在一瞬间变成天上半明半暗的云.那一年我二十一岁,在我一生的黄金时代.我有好多想法.我思索,想象,我不知该如何行动,我想知道一个城市 ...

最新文章

  1. 聊一聊多源最短路径问题(只有5行代码哦)
  2. thinkphp视频截图_thinkphp开发的搞笑视频网站
  3. 【面试必备】java实现下载文件
  4. Windows 技术篇 - 退出s模式解决surface无法安装和使用第三方应用问题:于安全和性能的考虑,此Windows模式只运行经Microsoft验证的应用
  5. c语言赋值小数,c语言中将一个浮点型赋值给整型时,会不会四舍五入?
  6. Java线程池深入理解
  7. 使用Docker 实现微服务并搭建博客,一文全掌握
  8. random---伪随机数生成器
  9. Oracle中的Round和Trunc
  10. 如何获取枚举字符串,值及遍历枚举(转)
  11. 平板电脑离寿终正寝还有多远?
  12. python切片长度_python的间隔切片技巧
  13. 什么不用 iframe 做微前端
  14. linux zfs raid,ZFS-自我恢复RAID
  15. 常用激活函数(激励函数)理解与总结
  16. 苹果Mac上的6 款值得开机启动的工具
  17. 问题 1125: 【C语言训练】委派任务*【最优解】
  18. cmd静默运行_如何在Win10上静默运行批处理文件
  19. Clickhouse求时间差
  20. python创建_python 创建txt并写入Python基础1 Hello World!

热门文章

  1. 【2022最新】手把手教你拥有自己的服务器与网站(无需备案)
  2. Linux 命令别名 alias(含“永久生效”方法)
  3. 京东商品关联版式,如何设置手机和电脑都显示?
  4. Matlab报错错误使用symengine
  5. 如何用C语言实现【爱心代码】
  6. ie退出全屏快捷键_IE浏览器快捷键,IE浏览器全屏快捷键
  7. Windows和Mac常用网络测试命令
  8. 【Android】安卓webview播放视频白屏解决方法
  9. 人体姿态识别-pose estimation
  10. linux命令 du -h --max-depth=0,查看当前目录下文件大小