构建调试Linux内核网络代码的环境MenuOS系统

Posted zhouzhouL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了构建调试Linux内核网络代码的环境MenuOS系统相关的知识,希望对你有一定的参考价值。

1.  构建MenuOS系统

  a). 下载linux内核并编译 (在虚拟机上自己实现一个小的linux操作系统)

      a.1) 实验环境: VMware虚拟机、64位Ubuntu16.04   

    a.2) 下载linux内核源码编译内核: 版本 linux-5.0.1(https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.1.tar.xz) 

    a.3) 解压缩文件: $ xz -d linux-5.0.1.tar.xz;  $ tar -xvf linux-5.0.1.tar

    a.4) $ cd linux-5.0.1  

   b).  安装内核编译工具

    $  sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev

  c).  配置编译内核

    $ sudo cp /boot/config-xxx -r .config    # 使用现存内核的配置文件:xxx指命令输入此处可以按Tab键补全

     $ sudo make oldconfig  # 应用现存配置文件

     $ sudo make localmodconfig  # 仅安装已有module

       $ sudo make menuconfig  # 配置其他编译选项  (依次选择Kernel hacking --> Compile-time checks and compiler options --> Compile the kernel with debug info, 保存退出)

     

    $ cd ~/MenuOS/linux-5.0.1  # 以上内核的准备工作结束, 开始编译内核

    $ sudo make   # 2019-12-20 09-02-31屏幕截图 进行内核配置,过程较慢

   

  c). 通过qemu虚拟机加载内核

   $ cd ../  

   $ sudo apt install qemu  # 安装qemu  

    $ qemu -kernel linux-5.0.1/arch/x86_64/boot/bzImage    # 运行该命令,安装成功则会弹出一个MenuOs系统窗口

   d).  构造MenuOS

     $  git clone https://github.com/mengning/menu.git

    $ mkdir rootfs  # 创建一个rootfs目录

    $ cd menu

    $ sudo apt-get install libc6-dev-i386  # 在64位环境下编译32位需安装

    # 在进一步执行前,需要先修改~/LinuxKernel/menu目录下Makefile文件下的一行内容

    # 将原qemu处的命令改为qemu-system-x86_64 -kernel ../linux-5.0.1/arch/x86_64/boot/bzImage -initrd ../rootfs.img

    

    $ make rootfs (成功则会出现如下界面)

    

   e).  验证MenuOS的网络可以正常工作 

    $ cd ~/LinuxKernel

    $ git clone https://github.com/mengning/linuxnet.git

    # 集成服务器到MENUOS上

    $ cd linuxnet/lab2

    $ make

    $ cd ../../menu/

    $ make rootfs  # 初始化根目录

    

    # 集成服务器到MENUOS上 (先修改lab3/makefile的qemu处的命令修改为qemu-system-x86_64 -kernel ../../linux-5.0.1/arch/x86_64/boot/bzImage -initrd ../rootfs.img )

    $ cd  ../inuxnet/lab3

    $ make rootfs

    # 可以观察到,现在多了replyhi和hello两个命令

    

    $ 直接在QEMU中输入hello命令, 输出如下,则网络正常工作

    

 2). 也可以实验楼线上直接运行MenuOS系统(实验楼课程地址:  https://www.shiyanlou.com/courses/1198)

    启动MenuOS系统 

       $ cd ~/LinuxKernel/    

    $ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img  # 直接启动内核 (initrd: 指定一个根文件系统)     

    # 成功运行MenuOS系统会跳出下面的界面(到此时,已经成功构建一个简单的linux系统)

    

2. 使用gdb跟踪调试信息

    a). 在qemu中重新启动gdb server (倘若在QEMU出现卡死状态,通过快捷键ctrl+alt即可解除该状态)

      $ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S  # 启动一个虚拟机qemu, 并且此时处于冻结状态

    b). 重新打开一个终端,执行gdb (相当于gdb client)

      $ gdb   # 启动gdb

     $ file linux-3.18.6/vmlinux   #  加载符号表

     $ target remote:1234   #  建立 gdb client 和 gdb server 之间的连接

     $ break start_kernel   #  在start_kernel处设置断点

     $ c    # 按 c 让qemu上的Linux继续运行, 即启动程序解除冻结 

     

     $ list    # 可以查看断点处  start_kernel 的源码 (即 已经验证 gdb可以跟踪到内核代码)

     

     # 到这一步已经验证我们成功构建了menuos系统并且可以使用gdb进行调试  

 3. 内核的启动过程简单介绍

  内核映像被加载到内存并获得控制权之后,内核启动流程开始。通常,内核映像以压缩形式存储,并不是一个可以执行的内核。

  因此,内核阶段的首要工作是自解压内核映像。

  内核编译生成vmliunx后,通常会对其进行压缩,得到zImage(小内核,小于512KB)或bzImage(大内核,大于512KB)。在它们的头部嵌有解压缩程序。

  linux内核的启动过程: 

    (CPU进入复位状态,内存数据清零,CS:IP(FFFF:0000)指向Bios的入口,系统通过此方法进入BIOS启动过程)    

    ==> 系统上电  
        ===> CPU自身初始化 

    ---------------------------------BIOS------------------------------------------  (BIOS启动,主要完成硬件初始化,包含以下两个过程)
          ===> 上电自检
            ===> 加载内核引导程序 (读入Boot Loader, 其主要作用是将系统启动代码读入内存)

    ------------------------------内核引导程序----------------------------------- (此时控制权转交给了Boot Loader,引导OS的启动)
              ===> 主引导程序
                ===> 次引导程序

    ----------------------------------------------------------------------------------  (已经将OS代码调入内存,将控制权转交给OS,OS的启动程序开始执行)
                  ===> 调用内核 (控制权在Setup.s程序处,之后它会将控制权交给Head.s, Head.s在最后将控制权交给main.c中的start_kernel函数,剩余的初始化工作皆由它完成)

  我们在start_kernel函数处设置断点,并继续执行MenuOs系统,得到下面的图

      

   可以看到此时在start_kernel函数处停止,此时已经完成了

   

   我们主要介绍一下Boot Loader 将控制权转交给OS后,从start_kernel开始到init的几个重要的初始化过程

// start_kernel()执行后,从内核态转到用户态,此时可以以用户的身份使用
linuxasmlinkage void __init start_kernel(void)
{
  ... 
  setup.arch();  // 基本硬件初始化
  ...
  paging_init(); // 完成页的初始化
  ...
  trap_init();   // 中断向量表初始化
  ...
  sched.init();  // 为进程调度执行做准备
  ...
  time_init();  
  ...
  console_init();  
  ...
  inode_init();  //  文件系统初始化开始
  ...
  mem_init();    // 结束后启动/etc下的配置文件,并进入用户态
  
}

参考来源:

  1. https://github.com/mengning/net/tree/master/lab3

  2. 深入分析Linux内核源码

以上是关于构建调试Linux内核网络代码的环境MenuOS系统的主要内容,如果未能解决你的问题,请参考以下文章

构建调试Linux内核网络代码的环境MenuOS系统

构建调试Linux内核网络代码的环境MenuOS系统

构建调试Linux内核网络代码的环境MenuOS系统

构建调试Linux内核网络代码的环境MenuOS系统

构建调试Linux内核网络代码的环境MenuOS系统

构建调试Linux内核网络代码的环境MenuOS系统