• 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

  • 相关阅读:
    zoj 3632 Watermelon Full of Water
    将字符串切割成数组 componentsSeparatedByString
    paip.C#.NET多线程访问 toolStripStatusLabel
    EBS后台取消死锁检查代码和取消死锁会话步骤经验
    Java泛型深入题目
    Win7下BootCamp蓝屏问题解决方案二
    一步步开发 Spring MVC 应用
    批处理获取U盘、可移动硬盘的盘符
    一种松耦合的分层插件系统的设计和实现
    分享一个开源的批量修改VC工程属性的小工具
  • 原文地址:https://www.cnblogs.com/yuchao123/p/9955137.html
Copyright © 2020-2023  润新知