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


    第三章 MenuOs的构造

    一.知识点总结

    • 计算机的三大法宝:
      • 存储程序计算机
      • 函数调用堆栈
      • 中断
    • 操作系统的两把宝剑:
      • 中断上下文的切换(保存现场和恢复现场)
      • 进程上下文的切换

    它们都和汇编语言有着密不可分的联系

    • Linux内核分析比较重要的是:
      • arch目录下的x86目录下的源文件
      • init目录下的main.c(其中的start_kernel函数是初始化Linux内核启动的起点
      • kernel目录下和进程调度相关的代码

    二.跟踪分析Linux内核启动过程

    1.实验过程

    通过下面的命令把Linux系统和一个简单的文件系统运行起来

    cd LinuxKernel/
    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
    


    使用gdb跟踪调试内核,添加-S(在CPU开始之前把他冻结起来)和-s(在1234端口上创建一个gdb-server,可以再另外打开一个窗口用gdb把带有符号表的内核镜像加载进来,然后连接gdb srever 设置断点追踪内核)两个参数。如下图,可以看到内核被冻结起来了。

    再打开一个窗口,启动gdb,把内核加载进来并且建立连接。
    在gdb中输入以下命令

    file linux-3.18.6/vmlinux 
    target remote:1234
    break start_kernel 
    c //按c让qemu上的Linux继续运行
    

    可以看到如下运行结果

    输入list可以查看到start_kernel上下的代码

    再设置一个断点rest_init继续执行

    可以看到 rest_init 是在 start_kernel 的尾部进行调用的。

    2.遇到的问题

    当我再打开一个窗口启动gdb的时候,在gdb界面中targe remote之前加载符号表的时候出现了问题,在同学的帮助下发现是在上一步启动内核的时候把QEMU的窗口关闭导致。

    3.分析start_kernel函数的执行过程

    asmlinkage __visible void __init start_kernel(void)
    {
        char *command_line;
        char *after_dashes;
        
        /*
         * Need to run as early as possible, to initialize the
         * lockdep hash:
         */
        lockdep_init();
        set_task_stack_end_magic(&init_task);// init_task即手工创建的PCB,0号进程即最终的idle进程
        smp_setup_processor_id();
        debug_objects_early_init();
        // ...
        trap_init();                          // 中断向量的初始化
        mm_init();                            // 内存模块的初始化
        sched_init();                         // 调度模块的初始化
        // ...
        rest_init();                          // rest_init是0号进程(是使用宏初始化的),它创建1号进程init和其他的一些服务进程
    }
    

    4.Linux系统启动的过程

    内核的主要模块的初始化工作都是在start_kernel函数里调用。

    idle进程是怎么来的:init_task()(PID=0)在创建init进程后,调用cpu_idle()演变成idle进程,执行一次调度之后,init进程运行。

    1号进程是怎么来的:1号内核线程负责执行内核的部分初始化工作及进行系统配置,最后调用do_execve加载init程序,演变成init进程(用户态1号进程),init进程是内核启动的第一个用户态进程。

    kthreadd(PID=2)进程由0号进程创建,始终运行在内核空间,负责所有内核线程的调度和管理。

    内核启动完成后,有一个call_cpu_idle,当系统没有需要执行的进程时就调用idle进程,即“0号进程”。idle进程从系统启动之后就一直存在,它创建了1号进程init和其他的一些服务进程,这样系统就启动起来了。

  • 相关阅读:
    centos7.3 安装 mysql5.7.13
    linux下MySQL的启动与访问
    使用jquery修改display属性
    浏览器在线预览pdf、txt、office文件
    查看java的jar包源码
    邮件群发器
    公司招聘asp.net程序员(已过期)
    javascript面向对象,实现namespace,class,继承,重载
    javascript window.close() 去掉那讨厌的确认对话框
    如果注定要分别
  • 原文地址:https://www.cnblogs.com/yangdd/p/11627191.html
Copyright © 2020-2023  润新知