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

第三章 MenuOS的构造

构造一个简单地Linux内核

第一步、构建Linux系统MenuOS

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

注:qemu仿真kernel;bzImage是vnLinux经过gzip压缩后的文件,是压缩的内核映像;initrd是内存根文件系统;rootfs是编译好的文件系统。

运行结果如图:

第二步、跟踪调试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之前,也可在之后

    效果如图:

    查看strat_kernel代码:

    分析: strat_kernel是一切的起点,用于完成硬件系统的初始化工作,为C代码的运行设置环境。

    其中,比较重要的init_task是手工创建的PCB,是进程描述符,0号进程,即最终的idle进程。

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

    break rest_init

    查看rest_init()代码:

    分析: 通过rest_init()新建kernel_init和kthreadd内核线程

    注:

    • init_task(0号进程)是唯一没有通过fork方式产生的进程;
    • 所有的内核线程都是直接或间接地一kthreadd为父进程。
  5. 总结进程创建过程

    • init_task()(PID为0)通过调用cpu_idle()转为idle进程,运行在内核空间;
    • init_task()创建的kernel_init()(1号内核线程)通过调用do_execve可转为init用 户态1号进程,这是内核启动的第一个用户态进程;
    • init_task()创建的kthreadd()(2号内核线程)始终运行在内核,负责所有内核线程的调度和管理。

    整个过程如图所示:

猜你喜欢

转载自www.cnblogs.com/liangxu111/p/11667802.html