《Linux内核分析》 第四节 扒开系统调用的三层皮(上)


张嘉琪 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、用户态、内核态和中断

1.用户态、内核态和中断的处理过程

  • 一般现代CPU都有几种不同的指令执行级别。

  • 在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别就对应着内核态。 而在相应的低级别执行状态下,代码的掌控范围会受到限制。只能在对应级别允许的范围内活动。

  • 举例:Intel x86CPU有四种不同的执行级别0-3,Linux只使用了其中的0 3级分别表示内核态和用户态

  • 为什么有权限级别的划分?

    是为了让操作系统本身更稳定的一种机制

  • cs寄存器的最低两位表明了当前代码的特权级。

  • CPU每条指令的读取都是通过cs:eip这两个寄存器:其中cs是代码段选择寄存器,eip是偏移量寄存器。

  • 上述判断由硬件完成。

  • 一般来说在Linux中,地址空间是一个显著地标志:0xc0000000以上的地址空间只能在内核态下访问,都可以访问0x00000000-0xbfffffff的地址空间在两种状态下。

    注意:这里说的地址空间是逻辑地址而不是物理地址。

  • 中断处理是是从用户态进入内核态的主要方式。

  • 系统调用只是一种特殊的中断。

  • 寄存器上下文

    • 从用户态切换到内核态时

      • 必须要保存用户态的寄存器上下文。
  • 中断/int指令会在堆栈上保存一些寄存器的值

    • 如:用户态栈顶地址、当时的状态字、当时的cs:eip的值。
  • 中断发生后的第一件事就是保存现场,结束前最后一件事是恢复现场

    • 保护现场就是进入中断程序 保存需要用到的寄存器的数据。

    • 恢复现场就是推出中断程序 恢复保存寄存器的数据。

  • 中断处理的完整过程

    • interrupt(ex:int 0x80)-save

      cs:eip/ss:esp/eflag(curret) to kernel stack,then load cs:eip(entry of a specific ISR)and ss:esp(point to kernel stack)

    • SAVE_ALL

      • ...//内核代码,完成中断服务,发生进程调度
    • RESTORE_ALL

    • iret-pop cs:eip/ss:esp/eflags from kernel stack

二、系统调用概述

  • 应用程序、封装例程、系统调用处理程序及系统调用服务例程之间的关系

三、使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

  • 实验报告

  • 选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/syscall_32.tbl 参考视频中的方式使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

  • 博客内容的具体要求如下:

    1. 题目自拟,内容围绕系统调用的工作机制进行,博客中需要使用实验截图

    2. 博客内容中需要仔细分析汇编代码调用系统调用的工作过程,特别是参数的传递的方式等。

    3. 总结部分需要阐明自己对“系统调用的工作机制”的理解。
  • 本次实验选择了2号调用fork调用来做实验:fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID

用实验楼的虚拟机打开shell

Cd Code
Vi forktest.c
Gcc forktest.c -o forktest.o -m32
./forktest.o

fork.c代码如下

#include <unistd.h>
#include <stdio.h>
int main ()
{pid_t fpid;int count = 0;fpid = fork();if (fpid < 0)printf("error in fork!");else if (fpid == 0) {printf("i am the child process, my process id is %d\n",getpid());count++;}else {printf("i am the parent process, my process id is %d\n",getpid());count++;}printf("count: %d\n",count);return 0;
}

 运行结果见截图 

  • 嵌入式汇编代码的执行,fork-asm.c源代码如下(参数的传递方式见注释):
#include <unistd.h>
#include <stdio.h>
int main ()
{pid_t fpid;int count = 0;
asm volatile ("mov $0, %%ebx\n\t"       "mov $0x2, %%eax\n\t"    // 将fork的系统调用号0x2赋值给eax"int $0x80\n\t"          // 通过0x80中断向量,执行系统调用"mov %%eax, %0\n\t"      // 系统返回的pid号默认储存在eax中: "=m" (fpid)            // 输出操作数0为内存中的fpid。);
if (fpid < 0) printf("error in fork!"); else if (fpid == 0) { printf("i am the child process, my process id is %d\n",getpid()); count++; } else { printf("i am the parent process, my process id is %d\n",getpid()); count++; } printf("count: %d\n",count); return 0; }

运行结果见截图

总结

调用一个系统调用经历了系统调用的三层皮。分别是系统调用函数api,中断向量systemcall,系统调用服务sysxyz。通过C嵌入汇编代码的实验可以比较清晰的了解系统调用过程。

 // 系统调用号默认通过eax传递,因此将fork的系统调用号0x2赋值给eax

转载于:https://www.cnblogs.com/Juliet5307/p/5277019.html

《Linux内核分析》 第四节 扒开系统调用的三层皮(上)相关推荐

  1. 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)

    黄胤凯   原创作品转载请注明出处   <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频学习 1 ...

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

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

  3. 第四周—扒开系统调用的“三层皮”

    [洪韶武 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ]  第四周 扒开系统 ...

  4. 作业4:扒开系统调用的三层皮(上) 20135115臧文君

    扒开系统调用的三层皮(上) 注:作者:臧文君,原创作品转载请注明出处,<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000 ...

  5. linux内核分析——扒开系统调用的三层皮(上)

    20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 系统调用 ...

  6. 《Linux内核分析》 第一节 计算机是如何工作的

    第一节 计算机是如何工作的 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-100002900 ...

  7. Linux内核分析(四)之“暗流涌动”

    一.拨云见日 身为程序员,我们绕不开系统调用,但是我们往往都是通过一个"中间人"--库函数与其打交道. 我们调用一个库函数也许看起来非常简单,但是其真正的实现细节,并非我们看起来那 ...

  8. 《Linux内核分析》 第二节 操作系统是如何工作的

    Linux内核分析 第二周 操作系统是如何工作的 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/UST ...

  9. 扒开系统调用的三层皮(下)

    5234+ 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1.给MenuO ...

最新文章

  1. 【物联网】NB-IoT简介
  2. ENAS pygraphviz 的替换之路
  3. linux vim 插件管理,linux: vim插件管理
  4. FFmpeg 硬件加速方案概览 (下)
  5. FileIo 删除类中的private方法
  6. [SCOI2009]最长距离
  7. 【C语言】排序(算法基础)
  8. 七个小技巧保护无线网络安全
  9. 泰山OFFICE正式在UOS应用商店上架
  10. Ubuntu编写第一个Python程序
  11. linux安全检查与加固报告,linux安全加固文档分析.doc
  12. matlab中面板数据格式,MATLAB空间面板数据模型操作介绍
  13. vue语音播放通知功能
  14. rar、zip优缺点
  15. java+s2sh+mysql报刊订阅系统系统
  16. Eureka(02-入门)Eureka是什么
  17. 【ARM汇编】第三章:ARM指令系统
  18. 东北农业大学计算机科学与技术复试名单,更新!最新182所院校复试信息汇总
  19. Redis底层数据结构详解(一)
  20. 世界上应用最广泛的算法之一的卡尔曼滤波算法原理-从放弃到精通-无人机/机器人应用

热门文章

  1. 顾维灏谈百度地图数据采集:POI自动处理率达90%
  2. zabbix简单的原理以及zabbix的部署
  3. 猴子吃桃问题——递归算法解答
  4. 测试工程师的分类有哪些?发展前景怎么样?
  5. 简述企业信息化的主要工作内容
  6. 如何用excel统计调查问卷
  7. ThinkPHP6+querylist 实战开发
  8. 前端程序员怎么样通过业余时间接单app、小程序订单
  9. C#发起钉钉审批实例,表格明细 FormComponentValues_的格式该如何传递的问题
  10. 基于java SpringMVC的在线考试管理系统