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

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

    一、实验:跟踪分析Linux内核的启动过程

    1、在终端输入以下命令

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

    可得

    2、用gdb跟踪调试内核
    输入以下命令
    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

    • -s参数:freeze CPU at startup (use ’c’ to start execution)
      即启动后冻结CPU
    • -S参数:shorthand for -gdb tcp::1234
      即选择端口1234启动
      另开终端窗口,进入Linuxkernel目录下输入gdb,在gdb下设置断点

    进行以下调试

    file linux-3.18.6/vmlinux  //加载符号表
    target remote:1234  //建立gdb和gdbserver之间的连接
    break start_kernel  //设置断点
    c   //让qemu上的linux继续运行
    break rest_init //设置另一个断点
    c  //继续执行
    

    可得

    二、分析实验与学习知识

    1、分析start_kernel函数的执行过程
    在终端输入
    cd LinuxKernel/linux-3.18.6/init

    找到main.c#500
    start_kernel代码如下图

    各个函数作用:

    sched_init():初始化调度模块
    build_all_zonelists():初始化内存管理
    page_alloc_init():初始化伙伴系统分配程序
    trap_init()、init_IRQ():初始化中断向量
    mm_init():初始化内存管理模块
    softing_init():软中断,初始化TASKLET_SOFTIRQ和HI_SOFTIRQ
    time_init():初始化系统日期时间
    kmem_cache_init():普通和高速缓存,初始化slab分配器
    calibrate_delay():延迟函数,用于确定CPU时钟
    kernel_thread():为进程1创建内核线程,这个内核线程又会创建其他的内核线程并执行/sbin/init程序。所有内核线程都是直接或间接地以kthreadd为父进程的
    kthreadd():管理和调度其他内核线程kernel_thread
    

    所以经过分析,知道其执行过程

    调用sched_init()函数初始化调度程序
    调用build_all_zonelists()函数初始化内存管理
    调用page_alloc_init()函数初始化伙伴系统分配程序
    调用trap_init()、init_IRQ()函数初始化IDT
    调用softing_init()函数初始化TASKLET_SOFTIRQ和HI_SOFTIRQ(软中断)
    调用time_init()初始化系统日期时间
    调用kmem_cache_init()函数初始化slab分配器(普通和高速缓存)
    调用calibrate_delay()函数用于确定CPU时钟
    调用kernel_thread()函数为进程1创建内个线程,这个内核线程又会创建其他的内核线程并执行/sbin/init程序
    在start_kernel()开始执行之后会显示linux版本,在init程序和内核线程执行的最后阶段还会显示很多其他信息。最后,就会在控制台上出现熟悉的登陆提示,通知用户Linux内核已经启动正在运行。
    

    2、分析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的内核线程,这一进程始终运行在内核空间,负责所有内核线程的调度和管理。

    3、Linux内核源码目录结构

    • arch:用于存放CPU体系结构的相关代码。
    • block:存放Linux存储体系中关于块设备管理的代码。
    • crypto:存放常见的加密算法的C语言代码。
    • Documentation:存放一些文档。
    • drivers:驱动目录,分类别存放了Linux内核支持的所有硬件设备的驱动源代码。
    • firmware:固件。
    • fs:文件系统,存放了Linux支持的各文件系统的实现。
    • include:头文件目录,存放公共的头文件。
    • init:存放Linux内核启动时的初始化代码。
    • lib:存放Linux的共用库文件。
    • mm:存放内存管理。
    • net:存放Linux网络的相关代码。

    三、总结

    本周学习了怎么构造一个简单的Linux内核,并通过gdb跟踪调试内核启动。通过阅读内核源码,学习了内核启动需要调用的函数的过程及步骤,受益匪浅。

  • 相关阅读:
    【Luogu P5515】[MtOI2019]灵梦的计算器
    简易的命令行入门教程
    8个接私活的网站,只要你有码,那“我”就有钱
    单表查询必会13条
    「Django」rest_framework学习系列-路由
    Linux下将时间修改为当地时间(通过ntpdate服务)
    iptables拒绝发起大量请求(针对单IP地址)
    .webp格式win7无法显示缩略图
    永久修改/etc/proc下的项的配置文件
    通过vsftpd实现虚拟用户登录,不同的用户登录不同的目录,使用不同的权限
  • 原文地址:https://www.cnblogs.com/camusxd/p/13894499.html
Copyright © 2011-2022 走看看