• Linux内核分析——扒开系统调用的三层皮(下)


    一、给MenuOS增加time和time-asm命令

    1、实验过程:

    rm menu -rf   强制删除

    git clone http://github.com/mengning/menu.git    克隆相关信息

    make rootfs    一个脚本,自动编译自动生成根文件系统,并自动启动MenuOS

     

    2、如何给MenuOS增加time和time-asm命令

      (1)更新menu代码到最新版

      (2)在test.c中的main函数里增加MenuConfig

      (3)增加对应的Time函数和TimeAsm函数

      (4)make rootfs 自动编译脚本

    二、使用gdb跟踪系统调用内核函数sys_time

    1、实验过程:

     

    2、使用gdb跟踪调试内核

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

      # 关于-s和-S选项的说明:

      # -S freeze CPU at startup (use ’c’ to start execution)

      # -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

    3、跟踪系统调用内核函数sys_time:

    gdb

       (gdb)file linux-3.18.6/vmlinux  //在gdb界面中targe remote之前加载符号表

       (gdb)target remote:1234  //建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行

     (gdb)b sys_time

       (gdb)c   //启动到MenuOs,在MenuOs中使用time,会停在time函数处

       (gdb)list  //对应代码

       (gdb)s    //单步执行

       (gdb)finish  //将这个函数执行完

    以上两步重复使用,可以看到sys_time函数中的函数,直到看见return i

    执行int 0x80之后执行system_call对应的代码

       (gdb)b system_call   //是可以设置断点的,但是这段是汇编代码,运行时不能在这个断点处停下逐句分析。

    system_call不是一个正常意义上的函数,只是一段汇编代码。

    三、系统调用在内核代码中的处理过程

    1、系统调用在内核代码中的工作机制和初始化

    (1)进系统调用机制的初始化:

     

    (2) trap_init里面有一个set_system_trap_gate函数,函数定义中有系统调用的中断向量SYSCALL_VECTOR和汇编代码入口system_call。

    (3)一旦执行int 0x80,CPU直接跳转到system_call来执行。

    2、简化后便于理解的system_call伪代码

    (1)伪代码:

     

    分析:    

       1)系统调用就是一个特殊一点的中断,所以也有保护现场与恢复现场。可以从上图中看到SAVE_ALL。

         2)sys_call_table是系统调用表

         3)syscall_after_all,需要先保存返回值

         4)没有sys_exit_work就restore_all,返回用户态。

         5)一旦进入sys_exit_work,里面会有一个进程调度时机。

    (2)简化后的伪代码:

     

     

    分析:

      1)从ENTRY(system_call)开始,下面有SAVE_ALL,也有sys_call_table系统调用表,对应的处理函数是:sys_call_table(,%eax,4)。

      2)判断当前任务是否需要处理sys_exit_work,如果不需要,就restore all,返回用户态。

      3)系统调用返回之前,可能发生进程调度,进程间通信可能有信号需要处理。

    3、简单浏览system_call到iret之间的主要代码

      (1)SAVE_ALL:保存现场

      (2)call *sys_call_table(,%eax,4):调用了系统调用处理函数,eax系统调用号,这段是实际的系统调用的服务程序。

      (3)restore_all

      (4)INTERRUPT_RETURN:实际上就是iret,是个宏,中断系统调用的处理过程,结束。在这个过程中会发生sys_exit_work,sys_exit_work中会有work_pending,work_pending中会有work_notifysig,用来处理信号

      (5)call schedule 决定进程调度代码。

      (6)跳转到restore_all,恢复现场。

    四、总结

    系统调用的处理过程可分成以下3步:

      (1)将处理机状态由用户态转为系统态。之后,由硬件和内核程序进行系统调用的一般性处理,即首先保护被中断进程的CPU环境,将处理机状态字PSW、程序计数器PC、系统调用号、用户找指针以及通用寄存器内容等压入堆栈,然后,将用户定义的参数传送到指定的地方保存起來。

      (2)分析系统调用类型,转入相应的系统调用处理子程序。为使不同的系统调用能方便地转向相应的系统调用处理子程序,在系统中配置了一张系统调用入口表。表中的每个表目都对应一条系统调用,其中包含该系统调用自带参数的数目、系统调用处理子程序的入口地址等。内核可利用系统调用号去查找该表,即可找到相应处理子程序的入口地址而转去执行它。

      (3)在系统调用处理子程序执行完后,恢复被中断的或设置新进程的CPU现场,然后返冋被中断进程或新进程,继续往下执行。

     

  • 相关阅读:
    【BZOJ】2209: [Jsoi2011]括号序列(splay)
    【BZOJ】1251: 序列终结者(splay)
    【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)
    【BZOJ】3781: 小B的询问(莫队算法)
    【BZOJ】3289: Mato的文件管理(莫队算法+树状数组)
    【BZOJ】2038: [2009国家集训队]小Z的袜子(hose)(组合计数+概率+莫队算法+分块)
    【SPOJ】7258. Lexicographical Substring Search(后缀自动机)
    vue 中 event.stopPropagation() 和event.preventDefault() 使用
    Vue 中 使用v-show
    Vue v-if以及 v-else 的使用
  • 原文地址:https://www.cnblogs.com/20135235my/p/5322737.html
Copyright © 2020-2023  润新知