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

一、学习总结

通过gdb我们可以给系统调用内核处里程序如sys_write, sys_time设置断点,并让程序停在断点处,进行断点跟踪系统调用处里过程。由于system_call是完全用汇编写就一个的函数,虽然我们也可以在system_call处设置断点,但却无法让系统停在system_call处,所以也无法通过单步跟踪学习其处里流程。但system_call是所有系统调用的入口,也是程序由用户态转入内核态执行时无法越过的一个函数,其重要性不言而喻,所以我们跟随老师简化的汇编代码以及源代码学习其主要的流程。

二、实验过程

实验环境是使用本课程配备的实验楼虚拟机环境,打开命令行客户端,cd LinuxKernel目录,使用命令rm -rf menu删除原来的代码,使用git clone https://github.com/mengning/menu.git获取menu的最新代码,然后 cd menu 进入menu子文件夹,使用gedti test.c打开文件,讲我上周实验的代码拷贝改写成为menu的两个菜单项,主要代码部分如下:

  1. int SayHello(int argc, char *argv[])
  2. {
  3. char* msg = "Hello World";
  4. printf("%s", msg);
  5. printf("\n");
  6. return 0;
  7. }
  8. int SayHelloAsm(int argc, char *argv[])
  9. {
  10. char* msg = "Hello World";
  11. int len = 11;
  12. int result = 0;
  13. __asm__ __volatile__("movl %2, %%edx;\n\r"
  14. "movl %1, %%ecx;\n\r"
  15. "movl $1, %%ebx;\n\r"
  16. "movl $4, %%eax;\n\r"
  17. "int  $0x80"
  18. :"=m"(result)
  19. :"m"(msg),"r"(len)
  20. :"%eax");
  21. printf("\n");
  22. return 0;
  23. }
  24. int main()
  25. {
  26. PrintMenuOS();
  27. SetPrompt("MenuOS>>");
  28. MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
  29. MenuConfig("quit","Quit from MenuOS",Quit);
  30. MenuConfig("time","Show System Time",Time);
  31. MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
  32. <strong>    MenuConfig("sayhello","Say Hello World",SayHello);
  33. MenuConfig("sayhello-asm","Say Hello World",SayHelloAsm);</strong>
  34. ExecuteMenu();
  35. }

这里主要就是加了两个菜单项 sayhello 和 sayhello-asm 及其对应的实现函数,保存 test.c 函数,使用 make rootfs 编译运行 menuos 系统,输入help 可以看到我们新加入的菜单:

使用 gdb 跟踪相关的函数过程,在我前述的博客中有笔记详细的描述,有兴趣的可以参考下:http://blog.csdn.net/sunyeyi/article/details/44517109,这里主要就是说明下,我们可以在 gdb 里使用 b system_call 设置断点,但是却无法让程序停在这个地方。当然网上也有资料提供了其他技术来跟踪这个函数,由于个人时间能力所限,没有去研究!

三、通过源代码分析 system_call 处理流程

先看下系统调用机制的初始化,在start_kernel函数中,trap_init函数就是完成系统调用初始化的。

  1. trap_init();

在trap_init()函数中,关键代码如下,通过中断向量,将system_call函数和0x80绑定:

\arch\x86\kernel\traps.c

  1. #ifdef CONFIG_X86_32
  2. set_system_trap_gate(SYSCALL_VECTOR, &system_call);
  3. set_bit(SYSCALL_VECTOR, used_vectors);
  4. #endif

据此,用户态代码只要执行 int 0x80 中断,就会由 system_call 函数来处里。

再来看看system_call源代码,http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/kernel/entry_32.S,490行处。

根据这段源代码,参考老师在视频中的讲述,我们可以得到system_call的简化流程图如下:

这里我们需要特别注意的就是,在系统调用system_call返回之前,会检查当前进程是否需要执行syscall_exit_work,如果不需要就restore_all,然后中断返回了;如果需要处里,那么就在syscall_exit_work流程中查看是否有进程信号需要处理,若有就处里,是否需要进程调度,若有就调用schedule,切换到其他进程执行;然后才restore_all,中断返回。

四、总结

通过中断向量表,int 0x80和system_call关联起来;system_call又是通过系统调用号,将每一个系统调用和特定的系统调用服务例程关联起来;在system_call返回用户态之前,会执行syscall_exit_work,work_notifysig,schedule等函数以应对可能的进程信号处理和进程调度。

Linux内核分析5的更多相关文章

  1. linux内核分析作业8:理解进程调度时机跟踪分析进程调度与进程切换的过程

    1. 实验目的 选择一个系统调用(13号系统调用time除外),系统调用列表,使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 分析汇编代码调用系统调用的工作过程,特别是参数的传递的方 ...

  2. Linux内核分析作业7:Linux内核如何装载和启动一个可执行程序

            1.可执行文件的格式 在 Linux 平台下主要有以下三种可执行文件格式: 1.a.out(assembler and link editor output 汇编器和链接编辑器的输出) ...

  3. linux内核分析作业6:分析Linux内核创建一个新进程的过程

    task_struct结构: struct task_struct {   volatile long state;进程状态  void *stack; 堆栈  pid_t pid; 进程标识符  u ...

  4. linux内核分析作业5:分析system_call中断处理过程

    1.增加 Menu 内核命令行 调试系统调用. 步骤:删除menu git clone        (tab) make rootfs 这就是我们将 fork 函数写入 Menu 系统内核后的效果, ...

  5. linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作

    一.实验 使用gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与他人雷同 int g(int x) { return x + 3; } in ...

  6. linux内核分析作业:操作系统是如何工作的进行:完成一个简单的时间片轮转多道程序内核代码

    计算机如何工作 三个法宝:存储程序计算机.函数调用堆栈.中断机制. 堆栈 函数调用框架 传递参数 保存返回地址 提供局部变量空间 堆栈相关的寄存器 Esp 堆栈指针  (stack pointer) ...

  7. linux内核分析作业3:跟踪分析Linux内核的启动过程

    内核源码目录 1. arch:录下x86重点关注 2. init:目录下main.c中的start_kernel是启动内核的起点 3. ipc:进程间通信的目录 实验 使用实验楼的虚拟机打开shell ...

  8. linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...

  9. 《Linux内核分析》期末总结

    Linux内核设计期中总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 前八周博客汇总及总结 Linux内核设计第一周——从汇编语言出发理解计算机工作原理 我们学习了汇编语言的基础知识,这一 ...

  10. 《Linux及安全》期中总结&《Linux内核分析》期终总结

    [5216 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK NINE ...

随机推荐

  1. Maven学习(十六)-----Maven插件

    Maven插件 Maven 是一个执行插件的框架,每一个任务实际上是由插件完成的.Maven 插件通常用于: 创建 jar 文件 创建 war 文件 编译代码文件 进行代码单元测试 创建项目文档 创建 ...

  2. loadrunner之做压力测试要做的准备

    前提B/S架构 1.要有个备库和主库保存一致 到时候做压力测试的时候,要断开主库连接到备库.进行测试.以免主库出现垃圾数据.2.节点 判断单节点能承受多大的压力,如200万的用户账号,10万的在线用户 ...

  3. 用Micro:bit做浇灌系统

    利用Micro:bit结合[土壤湿度感测棒]做一个简单的浇灌系统 一.测试土壤湿度感测棒 •材料:土壤湿度感测棒 (万能的淘宝上可以找到) •连接:将[土壤湿度感测棒]的一端接P0.另一端接GND 简 ...

  4. 前端--javaScript之简单介绍

    一.javaScript(以下简称js)的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端 ...

  5. 03-运行第一个docker容器

    环境选择 容器需要管理工具.runtime 和操作系统,我们的选择如下: 1.管理工具 - Docker Engine因为 Docker 最流行使用最广泛. 2.runtime - runc Dock ...

  6. sqlserver(2012)清理tempdb

    当数据库运行时间长了之后,tempdb变得特别大,几十G,受不了啊:当然我们知道重启 SQL Server服务的话,tempdb数据库会自动重新创建的,从而使 tempdb 回归到初始大小.但是这是生 ...

  7. Two Sum - 新手上路

    不是计算机相关专业毕业的,从来没用过leetcode,最近在学习数据结构和算法,用leetcode练练手. 新手上路,代码如有不妥之处,尽管指出来. 今天抽空做的第一个题:Two Sum(最简单的呃呃 ...

  8. day06 再谈编码 and 作业讲解

    1. 小数据池,(其他语言又叫常量池) id() 查看变量的内存地址 is和== is 判断内存地址是否一致 == 判断内容是否一致 小数据池的作用: 为了快速的创建字符串对象, 可以减少内存的浪费 ...

  9. Halcon如何保存仿射变换矩阵

    这里我们通过序列化来实现的,如下图,写到硬盘的HomMat2D_1内容和从硬盘里HomMat2D_2读出的内容一致,源代码在图片下方. Halcon源代码: hom_mat2d_identity (H ...

  10. New begin

    Purpose 今天更换了id,希望重新沉淀. 晚上看到国外一个博客,落款有个中文: 敬惜字纸. 共勉.