zoukankan      html  css  js  c++  java
  • 20189220 余超《Linux内核原理与分析》第六周作业

    系统调用的三层机制

    实验过程

    1.克隆MenuOS

    rm menu -rf //强制删除当前menu
    git clone http://git.shiyanlou.com/mengning/menu.git //重新克隆新版本的menu
    cd menu
    ls
    

    2.打开test.c并在里面添加上次实验所用的getpid的c函数和汇编代码

    3.在main函数中加入MenuConfig

    4.make rootfs

    5.使用hellp命令可以看到qemu中增加了我们先前添加的命令:

    6.执行新增加的命令getpid getpid_asm可得:

    7.gdb跟踪分析一个系统调用内核函数

    8.在start_kernel处设置断点,继续执行,在qemu窗口的结果:

    9.查看我所选用的系统调用的函数:

    10.设置断点在sys_getpid处,发现执行命令getpid时并没有停下,在执行getpid_asm时停下了:

    11.直接结束若干次单步执行,然后继续往下单步执行,发现出现了进程调度函数,返回了进程调度中的一个当前进程任务的值。

    12.设置断点于system_call处。发现可停,而继续执行时,刚才停下的getuid_asm也返回了值。

    实验分析

    1. 系统调用在内核代码中的工作机制和初始化
    • main.c中start_kernel函数:trap_init()
    • set_system_trap_gate(SYSCALL_VECTOR,&system_call)
    • SYSCALL_VECTOR:系统调用的中断向量
    • &system_call:汇编代码入口——执行int 0x80,系统直接跳转到system_call。

    2.系统调用——一个特殊的中断

    • SAVE_ALL:保存现场
    • call *sys_call_table(,%eax,4)调用了系统调度处理函数,eax存的是系统调用号,是实际的系统调度程序。
    • sys_call_table:系统调用分派表,syscall_after_all:保存返回值
    • 若有sys_exit_work,则进入sys_exit_work:会有一个进程调度时机。work_pending -> work_notifysig,用来处理信号 可能call schedule:进程调度代码可能跳转到restore_all,恢复现场。
    • 若无sys_exit_work,就执行restore_all恢复,返回用户态INTERRUPT_RETURN <=> iret,结束。
    在系统调用返回之前,可能发生进程调度,进程调度里就会出现进程上下文的切换。
    进程间通信可能有信号需要处理。
    可以将内核视为一系列中断指令的集合。
    

    3.system_call的流程示意图

    遇到的问题

    在进行gdb调试的时候,我导入文件的时候出现了下面的问题

    原因:是因为我进入到了menu里面去了,应该退出来回到LinuxKernel的目录下面来执行调试。

    回到上面的目录下载进行调试就可以导入文件了

    本章总结

    • 通过本章的学习和实验,我首先明白了系统调用是一种特殊的中断,初步理解了系统调用的过程。
    • 在系统调用时,我们需要SAVE_ALL,用于保存系统调用时的上下文。同样,中断处理的第一步应该也要保存中断程序现场。目的:在中断处理完之后,可以返回到原来被中断的地方,在原有的运行环境下继续正确的执行下去。
    • 在系统调用时,我们需要将系统调用号通过eax传入,通过sys_call_table查询到调用的系统调用,然后跳转到相应的程序进行处理。同样,中断处理时系统也需要有一个中断号,通过检索中断向量表,了解中断的类型和设备。
    • 系统调用时最后要restore_all恢复系统调用时的现场,并用iret返回用户态。同样,执行完中断处理程序,内核也要执行特定指令序列,恢复中断时现场,并使得进程回到用户态。

    在实验部分我学到了:给menuOS增加命令的方法:
    强制删除menu (rm menu -rf)
    更新menu代码至最新版本(git clone https://github.com/mengning/menu.git)
    在test.c中main函数中增加MenuConfig,以及增加上周自己选择Getegid,GetegidAsm的代码
    Make roofts自动编译,生成,和启动根文件系统

    使用gdb跟踪调试内核的方法:
    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
    gdb
    (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
    (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
    (gdb)break start_kernel # 断点的设置,注意寻找对应的系统调用函数名字,例如time命令对应sys_time

  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/yuchao123/p/9955137.html
Copyright © 2011-2022 走看看