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


    构造一个简单的Linux系统MenuOS

    使用gdb跟踪调试内核

    • 打开shell

    上述代码分析:
    qemu:启动已经安装在系统中的相当于虚拟机的程序qemu,这个程序为内核的启动提供一个上下文环境。
    -kernel 文件名+路径:启动内核,内核经过编译之后形成一个名为init的文件,之前已经将其拷贝到rootfs文件目录下,并通过cpio的方式将rootfs下的文件打包成一个名为roofs.img的镜像文件。
    -initrd rootfs.img:指定rootfs为为启动时的硬件驱动。

    • 使用gdb跟踪调试内核

    • 再另外打开一个shell窗口,用Ctrl+Shift+O实现水平分割,启动gdb,把内核加载进来,建立连接。

    • 设置断点start_kerenl 和 rest_init

    */	
    static __initdata DECLARE_COMPLETION(kthreadd_done);
    	
    static noinline void __init_refok rest_init(void)
    {
    int pid;
    
    rcu_scheduler_starting();
    /*
    

    简单分析start_kernel

    • 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);
            smp_setup_processor_id();
            debug_objects_early_init();
                    .............
    
            /* Do the rest non-__init'ed, we're now alive */
            rest_init();
     }
    
    • 分析

    start_kernel( )函数完成了Linux内核的初始化工作。每个内核部件都是用这个函数进行初始化的。

    1.调用sched_init()函数来初始化调度程序

    2.调用build_all_zonelists()函数俩初始化内存管理

    3.调用page_alloc_init()函数来初始化伙伴系统分配程序

    4.调用trap_init()函数和init_IRQ()函数以初始化IDT

    5.调用softing_init()函数初始化TASKLET_SOFTIRQ和HI_SOFTIRQ(软中断)

    6.调用time_init()初始化系统日期时间

    7.调用kmem_cache_init()函数初始化slab分配器(普通和高速缓存)

    8.调用calibrate_delay()函数用于确定CPU时钟(延迟函数)

    9.调用kernel_thread()函数为进程1创建内个线程,这个内核线程又会创建其他的内核线程并执行/sbin/init程序

    10.在start_kernel()开始执行之后会显示linux版本,除此之外,在init程序和内核线程执行的最后阶段还会显示很多其他信息。最后,就会在控制台上出现熟悉的登陆提示,通知用户Linux内核已经启动正在运行。

    总结

    • Linux内核启动过程为:

      • 最初执行的进程即是0号进程init_task,它是在系统初始化阶段由start_kernel()函数从无到有手工创建的一个内核线程,进程0在创建1号内核线程kernel_init后,调用cpu_idle()成为idle进程,而idle进程就是当系统没有进程需要执行的时候来调度用的。

      • 1号内核进程负责执行内核的部分初始化工作及进行系统配置,然后使用kernel_thread(kernel_init, NULL, CLONE_FS)函数(也就是fork方式)建立了pid=1的1号进程,也叫init进程(用户态1号进程),成为系统中的其他所有进程的祖先,当调度程序选择到init进程时,init进程继续完成剩下的初始化工作。然后调用kernel_thread执行kthreadd,创建PID为2的内核线程,这一进程始终运行在内核空间,负责所有内核线程的调度和管理。

  • 相关阅读:
    【蜕变之路】第20天 UUID和时间戳的生成 (2019年3月10日)
    3.EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)
    reactnative资源
    代码
    模板匹配模型、原型模型和区别性特征模型各自如何解释汉字的知觉
    mysqldatadir 转移
    mysql主从设置windows
    心灵鸡汤
    测试的发现遗漏BUG的做法
    汉字模式匹配的过程
  • 原文地址:https://www.cnblogs.com/Huyiming/p/11619862.html
Copyright © 2020-2023  润新知