• 2019-2020-1 20199311《Linux内核原理与分析》第六周作业


    1. 问题描述

    通过这一周的学习,我进一步了深入内核系统的调用处理过程,更加完整地理解了系统调用的工作机制。下面通过给MenuOs增加geteuid命令,以及通过gdb跟踪调用time函数的过程,并分析system_call代码对应的工作过程这两方面深入理解系统调用的工作机制。
    2. 解决步骤

    2.1 给MenuOs增加geteuid命令

    首先进入LinuxKernel目录,删除旧的menu目录,然后在github上克隆一个新的目录menu,进入menu,命令如下

    cd LinuxKernel
    rm -rf menu
    git clone https://github.com/menging/menu.git
    cd menu
    

    图片描述
    修改test.c文件,增加Geteuid函数(函数名避免与系统调用geteuid重复)
    图片描述
    使用如下命令生成根文件系统,并查看帮助,并运行geteuid命令

    make rootfs
    MenuOs>> help
    MenuOs>> geteuid
    

    图片描述

    2.2 gdb跟踪调用调试time函数

    2.2.1 调试步骤

    返回LinuxKernel目录,shift+ctrl+o水平分割,执行如下命令

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

    在gdb调试之前,先启动gdb,把3.18.6的内核加载进来,之后连接到target remote 1234,操作完成后,就连接到了需要调试的MenuOS。
    图片描述
    在start_kernel处设置断点,命令如下

    gdb
    file linux-3.18.6/vmlinux
    target remote:1234
    b start_kernel
    c
    

    图片描述
    图片描述
    在start_kernel处停下,time调用是13号系统调用对应的内核处理函数,即sys_time。接下来就可以在这里用b sys_time设置一个断点,启动MenuOS执行time命令,程序就会停到sys_time这个函数的位置,time命令执行到一半将卡在那里。
    图片描述
    在gdb中使用list命令,查看断点附件代码
    图片描述
    在gdb中使用命令s跟踪调试
    图片描述
    图片描述
    图片描述

    2.2.2 system_call汇编代码分析

    以上步骤主要跟踪了一个系统调用time,其中涉及系统调用对应的中断处理过程system_call,接下来将仔细分析system_call这个中断服务程序。
    system_call代码比较复杂,这里将代码简化并加上注释

    ENTRY(system_call)
               RING0_INT_FRAME
               ASM_CLAC
               pushl_cfi %eax                    #保存系统调用号
               SAVE_ALL                          #保存现场,将用到的所有CPU寄存器保存在栈中
               GET_THREAD_INFO(%ebp)             #ebp用于存放当前进程thread_info的结构地址
               testl $_TIE_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
               jnz syscall_trace_entry
      cmpl $(nr_syscalls),%eax                   #检查系统调用号
               jae syscall_badsys                #不合法,跳入异常处理
      syscall_call:
               call *sys_call_table(,%eax,4)     #通过系统调用号在系统调用表中找到相应的系统调用内核处理函数
               movl %eax,PT_EAX(%esp)
      syscall_exit:
               testl $_TIF_ALLWORK_MASK, %ecx    #检查是否有任务需要处理
               jne   syscall_exit_work           #需要,进入syscall_exit_work
      restore_all:
              TRACE_IEQS_IRET                    #恢复现场
      irq_return:
              INTERRUPT_RETURE                   #iret
    

    system_call流程示意图
    图片描述
    3. 总结

    通过这一周学习,我对linux内核系统调用处理过程有了更深入的了解,并且初步完整地学习了系统调用的工作机制。

  • 相关阅读:
    duilib布局
    C++中嵌入网页(duilib编辑框的实现)
    拖拽的实现
    调试URL(写文件)
    如何使用DataBinder.Eval()方法进行数据绑定
    GridVew,DataList,Repeater分页用户控件(第一版)
    关于何种情况下使用DataGrid、DataList或Repeater的一些讨论(转)
    使用PagedDataSource类实现DataList和Repeater控件的分页显示功能
    一个取得数据控件模板中输入框值的类
    在GridView中自定按钮,实现删除和更新
  • 原文地址:https://www.cnblogs.com/w-a-n-s-d-j/p/11743178.html
Copyright © 2020-2023  润新知