zoukankan      html  css  js  c++  java
  • 2019-2020-1 20199315《Linux内核原理与分析》第六周作业

    实验楼实验五

    实验楼环境研究MenuOS

    1.在MenuOS中添加并运行getpid命令

    进入LinuxKernel目录,删除menu目录

    
    $cd LinuxKernel
    $ls
    $rm -rf menu
    $ls
    
    

    从github上克隆一个menu,该版本中已经写了time和time_asm两个系统调用

    
    $git clone https://github.com/mengning/menu.git
    
    

    运行make rootfs对menu内文件进行编译,打开MenuOS输入help查询系统调用函数

    
    $cd menu
    $make rootfs
    
    

    输入help命令,测试新加入的time以及time-asm

    在menu目录中找到test.c文件打开(vim或gedit test.c),添加并写入getPid()方法,函数名应该避免与系统调用函数getpid()重复。

    
    int getPid(int argc,char *argv[]){
        int pid;
        pid=getpid();
        printf("pid=%d
    ",pid);
        return 0;
    }
    
    

    查看一下新扩展的两个函数,如橙色框所示;写入getPid()方法,如红色框所示

    再次使用make rootfs对menu内文件进行编译,由于test.c中通过MenuConfig()定义了调用函数名,在MenuOS中直接输入getPid可以调用,获得当前进程号,该进程也叫根进程。它负责产生其他所有用户进程。所有的进程都会被挂在这个进程下。

    实验中,发现不知道为什么,我的进程号大到如此惊人……

    一看原来是函数里面写错了:

    
    int getPid(int argc,char *argv[]){
        int pid;
        pid-getpid();  /* 是的,下面的printf中等号写成短横线就算了,这里都写错了2333 */
        printf("pid-%d
    ",pid);
        return 0;
    }
    
    

    改完之后又出现了新的问题……

    不知道咋搞= =,问了娄君也不得而知,索性关了重新编译了一次,没问题了……希望如果老师看到的话可以解疑QAQ

    1. gdb跟踪调用time函数的过程

    退回LinuxKernel目录,

    
    $cd ..
    
    

    shift+ctrl+o切换横屏,然后在终端1将QEMU挂起

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

    在终端2打开gdb,在start_kernel设置断点

    
    $gdb
    $file linux-3.18.6/vmlinux        /* 在gdb界面中targe remote之前加载符号表 */
    $target remote:1234           /* 建立gdb和gdbserver之间的连接,按c让qemu上的Linux继续运行 */
    $b start_kernel               /* 断点的设置可以在target remote之前,也可以在之后 */
    
    

    又连接超时了……

    过了会重启gdb又好了……

    设置断点

    程序执行到断点处

    继续执行,执行time命令,可发现此命令执行到一半卡住了,出现了一个断点。继续执行,直到出现return i

    设置断点(system_call),继续执行可发现time有返回

    实验分析

    system_call的代码:

    
    ENTRY(system_call)
        RING0_INT_FRAME    
        ASM_CLAC        
        pushl_cfi %eax                /* 保存系统调用号 */
        SAVE_ALL                      /* 可以用到的所有CPU寄存器保存到栈中 */
        GET_THREAD_INFO(%ebp)               /* ebp用于存放当前进程thread_info结构的地址 */
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
        jnz syscall_trace_entry
        cmpl $(nr_syscalls), %eax           /* 检查系统调用号(系统调用号应小于NR_syscalls) */
        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_IRQS_IRET                   /* 不需要,执行restore_all恢复,返回用户态 */
    irq_return:
        INTERRUPT_RETURN                /* 相当于iret */
    
    

    给MenuOS增加time和time-asm命令

    命令:1、强制删除:rm menu -rf

       2、克隆:git clone (后跟需要克隆数据所在的位置)

       3、自动编译,自动生成根文件系统,并自动启动:make rootfs

    给MenuOS增加time和time-asm命令步骤:

    1、更新menu代码到最新版

    2、在main函数中增加MenuCongfig

    3、增加对应的time和time-asm函数

    4、make rootfs

    使用gdb跟踪调用内核函数sys-time

    跟踪方法和上次所学内容一样:

    注:sys_time返回后进入汇编代码处理,gdb无法继续进行追踪

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

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

    1、系统调用机制的初始化

    
    initmain.c start_kernel
    
          trap_init()
    
    archx86kernel	raps.c
    
          #fdef CONFIG_x86_32
    
          set_system_trap_gate(SYSTALL_VECTOR,&system_call)(SYSTALL_VECTOR:系统调用的工作向量,&system_call:汇编代码的入口,系统执行int 0x80就跳转到该处执行)
    
          set_bit(SYSCALL_VECTOR,used_vectors)
    
          #endif
    
    

    2、system_call伪代码:

    system_call位置:/ arch/x86/kernel/entry_32.S中

    系统调用是特殊的中断:存在保存现场和恢复现场

    SAVE_ALL保存现场

    restore_all恢复现场
    call *sys_call_table(,%eax,4)调用系统调用函数:eax存的是系统调用号,根据系统调用号去找sys_call_table中的中断处理。
    INTERRUPT_RETURN,就是iret。

    分析system_call代码,系统调用的流程大致为:

    总结:

    发生中断时,CPU暂停执行当前程序,产生中断响应。中断响应主要工作是:
    (1)中止当前程序的执行;
    (2)保存原程断点现场
    (3)转到相应的处理程序。
    接着中断处理程序进行相应处理:
    (1)保存中断程序现场
    (2)分析中断原因,转入相应处理程序
    (3)调用中断处理程序
    (4)中断返回。

    此为本人Linux学习第六周的内容,如有不足,还请批评指正,不胜感激。

    以上

  • 相关阅读:
    剑指offer-二进制中1的个数
    [SHOI 2017] 分手是祝愿
    [SCOI 2010] 字符串
    [BZOJ 2653] middle
    [APIO 2015] 雅加达的摩天楼
    [NOI 2015] 品酒大会
    [SDOI 2015] 星际战争
    [Codeforces 715C] Digit Tree
    [TJOI 2018] 智力竞赛
    [CTSC 2018] 混合果汁
  • 原文地址:https://www.cnblogs.com/qianxiaoxu/p/11742083.html
Copyright © 2011-2022 走看看