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

    实验相关:

    尝试在自己的Ubuntu中来搭建实验所需要的环境。

    1.下载内核源码

    首先是下载内核源码(Linux-3.18.6)解压并编译,代码过程如下:

    mkdir LinuxKernel
    cd LinuxKernel
    wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xz
    xz -d linux-3.18.6.tar.xz
    tar -xvf linux-3.18.6.tar
    cd linux-3.18.6
    make i386_defcongig
    make
    


    在编译过程中遇到书中提到的相似的错误,提示不存在compiler-gcc9.h这一文件,查阅相关资料,是Ubuntu环境版本与gcc编译器版本不匹配的原因,进入到include/linux环境下,发现其中最高的版本为compiler-gcc5.h,解决这个问题的方法有两种,一是在网络上下载compiler-gcc9.h放入相应文件夹中,二是将compiler-gcc5.h复制重命名为compiler-gcc9.h后放入该文件夹中。实践中采用方法二解决该问题,成功编译。

    2.制作根文件系统

    代码如下:

    mkdir rootfs
    git clone https://github.com/mengning/menu.git
    cd menu
    gcc -pthread -o init linktable.c menu.c test.c -m32 -static
    cd ../rootfs
    cp ../menu/init ./
    find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
    

    其中执行

    gcc -pthread -o init linktable.c menu.c test.c -m32 -static
    

    时出现以下错误

    查阅后主要是gcc缺少32位的环境,使用命令

    apt-get install gcc-multilib
    

    安装multilib后解决问题,成功编译。

    3.启动不带调试信息的Linux内核和MennuOS

    自己环境中没有安装qemu,使用

    sudo apt-get install qemu 
    

    安装qemu后,依然提示无法找到qemu,返回usr/bin目录中查找,发现只存在qemu-system-i386

    通过Google后找到解决方法,可以建立一条软链接:

    sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu
    

    问题解决。

    输入

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

    启动成功

    接下来是对内核进行跟踪调试,重新配置编译Linux内核,代码如下:

    make menuconfig
    make
    

    重新配置编译Linux内核

    4.跟踪调试Linux内核的启动过程(使用gdb跟踪)

    (1)启动内核:

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s
    

    注:

    • -s:在1234端口上创建了一个gdb-server,可用于之后设置断点跟踪内核;
    • -S:使CPU初始化之前冻结起来。

    (2)启动gdb输入如下指令加载内核,建立连接

    file linux-3.18.6/vmlinux  //在gdb界面中target remote之前加载符号表
    target remote:1234  //用1234这个端口进行连接
    

    (3)gdb中输入如下指令在start_kernel处设置断点

    break start_kernel //可在target remote之前,也可在之后
    


    查看star_kernel函数:

    (4)gdb中输入如下指令在rest_init()处设置断点

    break rest_init
    

    查看rest_init()函数:

    (5)分析

    正如其名,strat_kernel是一切的起点,用于完成硬件系统的初始化工作,为C代码的运行设置环境。其中,比较重要的init_task是手工创建的PCB,是进程描述符,0号进程,即最终的idle进程。 通过rest_init()新建kernel_init和kthreadd内核线程。init_task()通过调用cpu_idle()转为idle进程,运行在内核空间;init_task()创建的kernel_init()(1号内核线程)通过调用do_execve可转为init用 户态1号进程,这是内核启动的第一个用户态进程;init_task()创建的kthreadd()(2号内核线程)始终运行在内核,负责所有内核线程的调度和管理。进程创建过程图如下图所示:

    sequenceDiagram participant idle进程,无限循环运行的内核态 participant init_task(0号进程)决定了系统所有进程、线程的基因 participant init用户进程,看所有其他用户进程的祖先进程 participant kernel_init()1号内核线程 participant kthreadd()2号内核线程,始终运行在内核空间,是所有内核态其他守护线程的父线程 init_task(0号进程)决定了系统所有进程、线程的基因->>idle进程,无限循环运行的内核态: 转为 init_task(0号进程)决定了系统所有进程、线程的基因->>kernel_init()1号内核线程: 演变 init_task(0号进程)决定了系统所有进程、线程的基因->>kthreadd()2号内核线程,始终运行在内核空间,是所有内核态其他守护线程的父线程: 创建 kernel_init()1号内核线程->>init用户进程,看所有其他用户进程的祖先进程: 转为

    5.尚未解决的问题(目前已解决)

    在自己的Ubuntu环境中使用gdb中会出现以下错误:

    查阅资料说是编译时没有正确设置-g选项,这个-g选项不能直接放在编译命令中,要在makefile的开头定义CFLAGS 变量:CFLAGS = -g ,这样list命令才能列出源代码。时间原因我在实验楼环境下完成了这部分的实验,这几天忙完后再来看这个错误怎么解决。
    6.后续补充

    尝试在

    gcc -pthread -o init linktable.c menu.c test.c -m32 -static
    

    中加入-g显示编译信息后成功通过,问题解决,猜测问题出在重新配置编译Linux内核中。重新检查后发现不知道什么原因导致compile the kernel with debug info未被选上,导致无法显示编译信息,再次选上后问题解决。

  • 相关阅读:
    python之字典操作
    python之元组操作
    初始超算
    后缀自动机
    博弈
    曼哈顿最小生成树
    莫队算法
    主席树
    [HNOI2014]世界树
    [SDOI2011]消耗战
  • 原文地址:https://www.cnblogs.com/mazhuhong/p/13882105.html
Copyright © 2011-2022 走看看