构建调试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系统的主要内容,如果未能解决你的问题,请参考以下文章