构建menuOS系统并跟踪查看内核源码
本次实验的主要内容是编译跟踪内核,过程真的是一波三折,不忍回首!
首先我们对ubuntu系统进行换源,加快其下载速度,步骤如下:
1. 备份源列表
Ubuntu配置的默认源并不是国内的服务器,下载更新软件都比较慢。首先备份源列表文件sources.list:
# 首先备份源列表
sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup
2. 打开sources.list文件修改
选择合适的源,替换原文件的内容,保存编辑好的文件, 以阿里云更新服务器为例(可以分别测试阿里云、清华、中科大、163源的速度,选择最快的):
# 打开sources.list文件
sudo gedit /etc/apt/sources.list
编辑/etc/apt/sources.list文件, 在文件最前面添加中科大镜像源:
deb https://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-security main restricted universe multiverse deb https://mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse deb-src https://mirrors.ustc.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
3. 刷新列表
sudo apt-get update sudo apt-get upgrade sudo apt-get install build-essential
下载速度瞬间就起飞了。
然后下载linux内核,解压,并执行进行编译
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.1.tar.xz xz -d linux-5.0.1.tar.xz tar -xvf linux-5.0.1.tar
cd linux-5.0.1
由于内核较大,我们选择allnoconfig模式进行编译;
编译成功!
由于wsl系统不支持图形化界面,所以我们要安装插件,步骤如下:
1. Windows安装VcXsrv
Install the lastest version of VcXsrv
2. WSL安装xfce desktop
sudo apt-get install xfce4-terminal sudo apt-get install xfce4 配置文件:~/.bashrc export DISPLAY=:0.0 export LIBGL_ALWAYS_INDIRECT=1
3. Windows上打开XLaunch
一般选“Multiple Window”
4. 现在执行WSL的图形界面程序就OK了
比如WSL 输入:startxfce4,XLaunch窗口就会跳出来以下窗口:
下面我们来使用qmue来加载内核;
sudo apt install qemu qemu-system-i386 -kernel linux-5.0.1/arch/x86/boot/bzImage # make i386_defconfig
启动menuos:
git clone https://github.com/mengning/menu.git cd menu sudo apt-get install libc6-dev-i386 # 在64位环境下编译32位需安装 make rootfs cd .. qemu-system-i386 -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img
结果如下:
Emmm,,,然后就卡死了,折腾一番之后就放弃了,还是用虚拟机吧。。。
重复以上步骤,然后启动menuOS,得到以下界面:
查阅资料,分析bzImage生成过程:
1、找到执行目标bzImage
make bzImage → /top/Makefile → /top/arch/i386/Makefile MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot vmlinux: arch/i386/vmlinux.lds bzImage: vmlinux @$(MAKEBOOT) bzImage
注解:在这里make bzImage才得以被执行,注意这里表要依靠目标vmlinux,同时给目标vmlinux增加ld脚本arch/i386/vmlinux.lds,而vmlinux定义在/top/Makefile中,当vmlinux完全生成后,才会执行下面的@$(MAKEBOOT) bzImage。
2、vmlinux的生成
A make bzImage → /top/Makefile vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o / --start-group / $(CORE_FILES) / $(DRIVERS) / $(NETWORKS) / $(LIBS) / --end-group / -o vmlinux
注解:这里CONFIGURATION没有用,在使用.config当前条件下可以认为未定义,make在碰到该未定义关键字时自动略过。而回到这里的时候,vmlinux的依赖已经变成了$(CONFIGURATION) init/main.o init/version.o linuxsubdirs arch/i386/vmlinux.lds 。至于其他的定义,分别如下:
CROSS_COMPILE = TOPDIR := $(shell if [ " PWD"!=""];thenechoPWD"!=""];thenecho PWD; else pwd; fi) LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o(注意和下面对CORE_FILES的扩展) SUBDIRS =kernel drivers mm fs net ipc lib
另外在经过/top/arch/i386/Makefile之后:
LD=$(CROSS_COMPILE)ld -m elf_i386 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S LDFLAGS=-e stext LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS) vmlinux: arch/i386/vmlinux.lds HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib
可见这些变量定义已经被找到,同时LD以及OBJCOPY还被重新定义,vmlinux增加了依赖。
然后我们再来构建menuOS的网络功能;
1、 将TCP服务端集成到menuOS系统中;
cd ~/LinuxKernel git clone https://github.com/mengning/linuxnet.git cd linuxnet/lab2 make cd ../../menu/ make rootfs
这时需要修改makefile文件,把test_reply.c的内容复制到menu的test.c中,syswrapper.h文件复制到menu文件夹下,然后就OK啦~
2、 将TCP客户端集成到menuOS系统中;
cd linuxkernel git clone https://github.com/mengning/linuxnet.git cd linuxnet/lab3 make rootfs
这次就没有报错;
查看结果:
然后再来跟踪内核代码;
首先执行如下指令,menuOS会在启动过程中停止;
qemu-system-x86_64 -kernel linux-5.0.1/arch/x86_64/boot/bzImage -initrd rootfs.img-append nokaslr -s -S
然后,重新打开一个终端窗口设置断点;
file ~/LinuxKernel/linux-5.0.1/vmlinux target remote:1234 break start_kernel #设置断点在start_kernel函数 c list #查看上下文
然后成功跟踪到内核源码;
同样的方法可以跟踪到socket部分的源码,这在我之前的一篇博文中展示过,链接如下:
https://www.cnblogs.com/philao/p/11938234.html
为了更好地理解linux系统的启动流程我从网上找到了这张示意图: