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


    1.问题描述

    在前面的文章中,学习了系统调用的相关理论知识,并使用库函数API和C代码中嵌入汇编代码两种方式使用getpid()系统调用。本文将内容围绕系统调用system_call的处理过程,在MenuOS中运行getpid命令,通过gdb跟踪调用time函数的过程,并分析system_call代码对应的工作过程。

    2.解决过程

    2.1 在MenuOS中运行getpid命令

    进入LinuxKernel目录,删除menu目录,然后从github上克隆一个menu。该版本中已经写了time和time_asm两个系统调用,进入menu目录,运行make rootfs对menu内文件进行编译,打开MenuOS输入help查询系统调用函数如下所示:

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

    由于test.c种通过MenuConfig()定义了调用函数名,在MenuOS中直接输入pid可以调用,获得当前进程为1,该进程也叫根进程。它负责产生其他所有用户进程。所有的进程都会被挂在这个进程下。

    2.2 gdb跟踪调用time函数的过程

    退回LinuxKernel目录,shift+ctrl+o切换横屏,然后在终端1执行如下命令:

    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
    target remote:1234
    b start_kernel
    


    可以看到,MenuOS在start_kernel处暂停,继续执行后面的程序,在sys_time函数中设置断点,在MenuOS中输入time后执行gdb,执行情况如下:

    sys_time函数执行至SYSCALL_DEFINE1处,调用list,可以显示当前断点附近代码内容:

    对sys_time函数进行跟踪,最终显示系统时间:


    2.3 system_call代码对应的工作过程分析

    在system_call处设置断点,但是gdb不支持单步跟踪,MenuOS中仍停留在sys_time这个位置:

    编辑linux-3.18.6/arch/x86/kernel/entry_32.S,查看system_call函数代码:



    原因是system_call不是一个正常的函数,只是一段汇编代码的起点,内部没有严格遵守函数调用堆栈基址,不支持gdb一条一条的调试。
    分析system_call代码,系统调用的流程大致为:

    3.总结

    本文主要学习了Linux内核系统调用的过程,并通过gdb和代码分析了调用过程。一般情况下,在用户态调用time()函数时,实际上调用了系统函数sys_time(),而用户态中有一个系统调用库函数xyz(),里面通过中断向量0x80触发system_call中断服务程序入口这段汇编代码,由用户态切换到内核态。首先通过SAVE_ALL保护现场,然后通过system_call函数中调用分配表找到系统调用内核处理函数指针,调用函数后通过restore_all和INTERRUPT_RETURN(iret)恢复现场并返回系统调用到用户态结束。以上system_call调用为软中断,和其他所有中断类似,可以推广到一般的中断处理过程。

  • 相关阅读:
    Django forms组件
    Django 分页器
    Django Ajax
    Django 多表操作2
    js12种应该注意的地方
    Web自动化测试python环境中安装 --selenium安装、火狐和火狐驱动版本、谷歌和谷歌驱动版本、测试
    python学习-文件操作
    关于redis搭建环境
    扩展知识
    javascript之Banner图片焦点轮播
  • 原文地址:https://www.cnblogs.com/louhao-20199310/p/11734977.html
Copyright © 2020-2023  润新知