zoukankan      html  css  js  c++  java
  • 2019-2020-1 20209329《Linux内核原理与分析》第四周作业

    《Linux内核原理与分析》第四周作业

    一、启动menu系统

    在实验楼的配置环境打开shell,内核启动完成后将进入menu程序

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


    二、跟踪调试内核

    在shell中输入以下命令

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 
    
    # 关于-s和-S选项的说明:
    # 1. -S
    #   -S freeze CPU at startup (use ’c’ to start execution)
    # 2. -s
    #   -s shorthand for -gdb tcp::1234 
    # 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
    


    创建多一个窗口,方便调试

    在下面的窗口,输入以下命令调试内核

    # 打开 GDB 调试器
    $ gdb
    
    # 在 GDB 中输入以下命令:
    
    # 在gdb界面中targe remote之前加载符号表
    (gdb)file linux-3.18.6/vmlinux 
    
    # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
    (gdb)target remote:1234
    
    # 断点的设置可以在target remote之前,也可以在之后
    (gdb)break start_kernel 
    


    断电设置好后,输入c,继续运行,程序将在函数start_kernel暂停

    使用list,查看函数start_kernel的上下文

    继续在rest_init处设置断点,然后输入c,开始调试

    使用list,查看函数rest_init的上下文

    start_kernel执行过程

    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内核已经启动正在运行。
    

    三、分析结果

    start_kernel()函数在main.c中起充当main函数的作用,在此函数被调用之前,内核代码主要是用汇编语言写的,用于完成硬件系统的初始化工作。在start_kernel函数在开始运行后,它会调用各个内核模块的初始化函数,主要包括:trap_init()中断向量初始化,mm_init()内存管理初始化,sched_init()调度模块初始化等,在整个的初始化过程中有一个init_task,它是一个进程描述符,负责内核模块的初始化,也就是0号进程,0号进程会新建kernel_init线程(1号内核线程)和kthreadd线程(2号内核线程),初始化工作完成后,init_task()调用cpu_idle()转化为ideal空进程。
    0号进程由系统自动创建, 运行在内核态,其前身是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。完成加载系统后,演变为进程调度、交换。
    1号进程由idle通过kernel_thread创建,在内核空间完成初始化后,加载init程序,由0进程创建,完成系统的初始化,是系统中所有其它用户进程的祖先进程。Linux中的所有进程都是有init进程创建并运行的。首先Linux内核启动,然后在用户空间中启动init进程,再启动其他系统进程。在系统启动完成完成后,init将变为守护进程监视系统其他进程。
    2号进程由idle通过kernel_thread创建,并始终运行在内核空间, 负责所有内核线程的调度和管理。它的任务就是管理和调度其他内核线程kernel_thread, 会循环执行一个kthread的函数,该函数的作用就是运行kthread_create_list全局链表中维护的kthread, 当我们调用kernel_thread创建的内核线程会被加入到此链表中,因此所有的内核线程都是直接或者间接的以kthreadd为父进程。

  • 相关阅读:
    使用 HTTP 缓存机制提升系统性能
    白鹭分析
    HTML5屏幕适配标签设置
    深入了解使用egret.WebSocket
    VS2013配合EgretVS开发简单塔防游戏
    C++高级语言程序设计实验五-中国矿业大学
    C++高级语言程序设计实验四-中国矿业大学
    C++高级语言程序设计实验三-中国矿业大学
    C++高级语言程序设计实验二-中国矿业大学
    C++高级语言程序设计实验一-中国矿业大学
  • 原文地址:https://www.cnblogs.com/Alannic/p/13912255.html
Copyright © 2011-2022 走看看