• 作业3:构造一个简单的Linux系统MenuOS 20135115臧文君


    构造一个简单的Linux系统MenuOS

    注:作者:臧文君,原创作品转载请注明出处,《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

    一、Linux内核源代码介绍

    1、根目录

    arch/x86目录下的代码是我们重点关注的,arch中包括支持不同CPU的源代码。

    init目录下包含内核启动相关的代码,如main.c(start_kernel函数相当于普通C程序的main函数,是Linux内核初始化的起点)。

    ipc:进程间通信

    kernel:Linux内核的核心代码

    关注readme文件

    二、构造一个简单的Linux系统MenuOS

    <步骤指导>

    1、在实验楼环境下:

    cd LinuxKernel/

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

    即可启动内核,完成后进入menu程序,支持三个命令help、version和quit。

    2、使用自己的Linux系统环境搭建MenuOS的过程

    # 下载内核源代码编译内核

    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_defconfig

    make # 一般要编译很长时间,少则20分钟多则数小时

    # 制作根文件系统

    cd ~/LinuxKernel/

    mkdir rootfs

    git clone https://github.com/mengning/menu.git  # 如果被墙,可以使用附件menu.zip 

    cd menu

    gcc -o init linktable.c menu.c test.c -m32 -static –lpthread(init是第一个用户态进程,是1号进程,采用的是静态编译的方式)

    cd ../rootfs

    cp ../menu/init ./

    find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img(img镜像文件)

    # 启动MenuOS系统

    cd ~/LinuxKernel/

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

    3、重新配置编译Linux使之携带调试信息

    (1)在原来配置的基础上,make menuconfig选中如下选项重新配置Linux,使之携带调试信息

    kernel hacking—>

    [*] compile the kernel with debug info

    (2)make重新编译(时间较长)

    4、使用gdb跟踪调试内核

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # 关于-s和-S选项的说明:

    # -S freeze CPU at startup (use ’c’ to start execution)

    # -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

    另开一个shell窗口

    gdb

    (gdb)file linux-3.18.6/vmlinux # 在gdb界面中target remote之前加载符号表    file home/shiyanlou/LinuxKernel/vmlinux

    (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行

    (gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后

    三、跟踪调试Linux内核的启动过程

    1、之前内核启动被冻结,断点设置完成后,打C回车可以恢复启动。

    命令:(gdb)list查看断点前后的代码

     

    在rest_init()前设置断点:break rest_init(),再按C运行,list查看代码。

     

    2、简单分析一下start_kernel

    在init目录下的main.c中

     

    全局变量init_task,即手工创建的PCB,0号进程即最终的idle进程。

    不管分析内核的哪一部分都会涉及到start_kernel。

     

    trap_init();初始化中断向量

    例:set_system_trap_gate(SYSCALL VECTOR,&system_call)系统陷阱门(系统调用)

    mm_init();内存管理模块

    sched_init();系统调度模块

    start_kernel中的最后一句:rest_init();在start_kernel从内核一启动就一直存在,是0号进程。

    0号进程创建了1号进程kernel_init。

    当系统没有进程需要执行时就调度到idle进程。

     

    道生一,一生二,二生三,三生万物。

    实验报告:

    1、cd home/YL/menu/rootfs,启动linux内核:qemu-system-x86_64 -kernel /boot/vmlinuz-4.3.0-kali1-amd64 -initrd ../rootfs.img

    注:find . | cpio -o -Hnewc | gzip -9 > ../rootfs.img将当前目录下的所有文件打包压缩生成img镜像文件

     

     

    2、qemu-system-x86_64 -kernel /boot/vmlinuz-4.3.0-kali1-amd64 -initrd ../rootfs.img -s -S,启动linux内核,停在起始部位,设置断点进行调试。

     

    3、重新开一个终端窗口,输入gdb,可以使用help命令查看可选择的命令。

     

    4、在gdb界面中target remote之前加载符号表:先切换到usr/src/linux-source-4.4路径下,然后输入命令file vmlinux。再建立gdb和gdbserver之间的连接:target remote:1234。

     

    5、在start_kernel前设置断点:break start_kernel,按c 让qemu上的Linux继续运行

     

    总结:

          这次实验是构造一个简单的linux系统MenuOS,使用老师已经配置好的虚拟机,做起来比较方便,但因为linux内核的版本不同以及配置的原因,所以在命令的使用上与网课中介绍的有一些差别,主要是路径的不同,在理解了各个命令中参数的含义后,命令使用起来会比较容易,实验也能顺利的进行。

          在课上的巩固讲解中,我了解到linux内核启动的三要素是:kernel,initrd和root所在分区。对于内核启动,最重要的命令就是:qemu-system-x86_64 -kernel /boot/vmlinuz-4.3.0-kali1-amd64 -initrd ../rootfs.img。在之后的gdb调试过程中,要注意路径!

          start_kernel是内核启动的起点,存在于init目录下main.c文件中。init_kernel即手工创建的PCB,0号进程即最终的idle.不论分析内核的哪一部分都会涉及start_kernel,模块初始化时需要调用start_kernel。在start_kernel中最后一句rest_init是start_kernel从内核启动时就一直存在的0号进程,0号进程创建了1号进程和其他的内核服务线程。

  • 相关阅读:
    ngInclude与script加载模板
    ng-model-options
    angular模板加载 ----ng-template
    ngBind ngBindTemplate ngBindHtml
    ng-switch
    ng-show与ng-if区别
    运维教给我什么
    路漫漫其修远兮,吾将上下而求索
    那些让我们继续坚持下去句子
    随手记
  • 原文地址:https://www.cnblogs.com/CatherineZang/p/5270066.html
Copyright © 2020-2023  润新知