操作系统内核分析 实验一 Linux系统启动过程
需要的基本工具及文件:
- VMware Workstation 15 player
- ubuntu-18.04.3-desktop-amd64.iso镜像文件
- Linux源码
- busybox源码
一、准备实验环境
(一)、下载ubuntu镜像
- 进入 ubuntu 官网下载页,如图1。
- 点击 Ubuntu Desktop,进入图2。
- 再点击 Ubuntu 18.04.3 LTS 版本右侧的 Download ,开始下载。
- 得到 ubuntu-18.04.3-desktop-amd64.iso 镜像文件。
(二)、安装Ubuntu虚拟机
- 进入VMware官网,按下图下载 VMware Workstation 15 Player ,安装完成后继续,此处安装过程省略。
- 打开 VMware Workstation 15 Player ,点击 创建新虚拟机 ,之后按图5操作,之后耐心等待安装完成。
- 安装结束,自动进入登录界面,可点击之前简易安装创建的用户,输入密码登录。到此安装Ubuntu虚拟机完成。
二、配置、编译linux内核以及busybox
因为刚开始学Linux,本文产生文件统一放在桌面,便于理解。大家可以按照自己需要,自行修改教程中的命令代码,选择存放位置。 若自行修改了文件路径,后面使用该文件时,也请注意修改文件路径
(一)安装开发套件及工具
- 在桌面右键单击,选择
Open Terminal
菜单项,进入终端界面。 - 在命令提示符后面,依次输入执行以下命令,过程中需要输入账户密码。
sudo apt update #检查更新 sudo apt install build-essential #基本开发套件 sudo apt install gcc-multilib sudo apt install git #分布式版本控制系统
- 安装结束后,可通过
gcc --version
检验gcc安装是否成功,成功将显示gcc版本信息。
同样,也可通过git --version
检验git安装是否成功,成功将显示git版本信息。 - git配置(仅使用git克隆远程仓库,可跳过此步):
git config --global user.name "nickname" #其中nickname,改成你想要的用户名 git config --global user.email "XXX@mail.com" #XXX@mail.com,改成你的个人邮箱
- 获取Linux源码和Busybox源码到桌面,时间因网速而异,耐心等待。执行完,会在桌面生成一个名为
linux
的文件夹和一个名为busybox
的文件夹。cd ~/Desktop #改变路径,用于后面克隆代码到桌面 git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux.git #linux内核源码(国外源较慢,这里从清华大学镜像服务器获取内核源码) git clone git://git.busybox.net/busybox #Busybox 是一个集成了大多数常用 Linux 命令 和工具的软件。
- 安装编译内核所需的软件包
sudo apt install flex sudo apt install bison sudo apt install libncurses5-dev sudo apt install pkg-config sudo apt install libglade2-dev sudo apt install libssl-dev sudo apt install libelf-dev
(二)配置、编译linux内核
- 首先进入linux文件夹
cd ~/Desktop/linux
- 清除以前的编译结果及配置信息(可跳过)
若之前有配置、编译过内核可执行该操作清除编译、配置结果,对于新克隆的源码可跳过此步make mrproper
- 配置linux内核
make defconfig #配置内核(按默认选项配置) make menuconfig #进入图形化的内核配置界面,自定义配置
进入图形化的内核配置界面后,接着按下面操作 1)按【↓】箭头键,找到最下面的 Kernel hacking,按【enter】键进入该配置项 2)按【↓】箭头键,找到 Compile-time checks and compiler options ,按【enter】键进入该配置项 3)按【↑】【↓】箭头键调整选项,找到 Compile the kernel with debug info,按【空格键】选中 4)此时,出现一些Compile the kernel with debug info的子配置项,找到Provide GDB scripts for kernel debugging,也按【空格键】选中 5)连按两下【ESC】键,退出该配置项,再连按两下【ESC】键,退回配置主页。 6)找到并回车进入 Processor type and features 选项,再在接近底部的Build a relocatable kernel 项下,按【空格键】去掉配置项Randomize the address of the kernel image (KASLR) 7)多次连按【ESC】,退出配置,此时提示是否希望保存新的配置,回车选择Yes。回到终端,继续执行本文后面命令。
- 编译linux内核
make #编译内核,持续时间比较久,耐心等待
(三)配置、编译busybox
-
配置 Busybox,生成配置文件
cd ~/Desktop/busybox #进入之前克隆的busybox源码目录 make defconfig #配置 Busybox,生成配置文件(按默认选项配置) make menuconfig #进入图形化的配置界面
进入图形化的配置界面后,接着按下面操作 1) 进入Setting --直接按【enter】进入配置组 2) 按【↓】箭头键,找到构建选项 build options 3) 按【↓】箭头键,找到构建选项下的 build static binary (no shared libs),按【空格键】,选中 4) 按下【esc】退出配置组 5) 再按下【esc】,提示保存修改,按【enter】键选择 yes 确认保存 6) 配置完成,回到终端继续执行本文后面命令
-
编译busybox
make install -j2 #编译busybox #-j 参数指定了可并行执行的作业数,通常设为计算机 CPU 数目的两倍以提高编译速度。 # 持续时间一丢丢久,耐心等待,直到显示 # -------------------------------------------------- # You will probably need to make your busybox binary # setuid root to ensure all configured applets will # work properly. # --------------------------------------------------
三、用 Busybox 制作根文件系统
-
进入桌面文件夹
cd ~/Desktop
-
创建 100M 磁盘镜像 rootfs.img
dd if=/dev/zero of=rootfs.img bs=1M count=100
-
在磁盘镜像中创建 ext4 根文件系统
mkfs.ext4 rootfs.img
-
挂载刚刚创建的根文件系统
mkdir rootfs sudo mount -o loop rootfs.img rootfs #需要输入密码
-
创建文件夹
cd rootfs sudo rm -rf lost+found sudo mkdir -pv {bin,sbin,etc/init.d,proc,sys,usr/{bin,sbin},tmp,dev}
-
在根文件系统上安装 busybox
sudo cp -drv ~/Desktop/busybox/_install/* . sudo chmod u+s bin/busybox #给bin文件夹下busybox文件设置setuid标志 #即 使文件在执行阶段具有文件所有者的权限
-
创建系统配置文件 /etc/inittab (若权限不足,则先执行sudo bash)
sudo cat > etc/inittab << EOF
出现大于号【>】形状的提示符后,复制下面五行代码,粘贴进去(代码前面无空格) ::sysinit:/etc/init.d/rcS ::respawn:-/bin/sh ::restart:/sbin/init ::shutdown:/bin/umount -a -r EOF
-
创建系统设置脚本 /etc/init.d/rcS
sudo cat > etc/init.d/rcS << EOF
出现大于号【>】形状的提示符后,复制下面十行代码,粘贴进去(代码前面无空格) #!/bin/sh echo "INIT SCRIPT" mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t debugfs debugfs /sys/kernel/debug mount -t tmpfs tmpfs /tmp mdev -s mount -n -o remount,rw / echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n" EOF
-
赋予rcS文件执行权限
sudo chmod +x etc/init.d/rcS
-
卸载根文件系统
cd ../ sudo umount rootfs
若卸载时提示
target is busy
,则执行fuser -v rootfs
查看占用rootfs的进程。
查看没什么特别大的问题,则执行fuser -k rootfs
可以直接结束使用rootfs文件的进程。
然后可能需要打开终端,cd ~/Desktop
进入桌面后,再次卸载根文件系统sudo umount rootfs
。
四、运行及调试内核
-
安装 qemu 虚拟机软件
sudo apt install qemu
-
在 home 目录下创建 .gdbinit 文件
cd /home cat > ~/.gdbinit << EOF
出现大于号【>】形状的提示符后,复制下面2行代码,粘贴进去(代码前面无空格) add-auto-load-safe-path path/to/linux EOF
-
qemu 创建并运行虚拟机
sudo qemu-system-x86_64 -kernel ~/Desktop/linux/arch/x86_64/boot/bzImage -hda ~/Desktop/rootfs.img -append "console=ttyS0 root=/dev/sda" -nographic -s -S #执行该命令之后,因为加了-S参数,会挂起虚拟机,所以没有执行迹象请不要惊慌,继续后面步骤
【部分参数说明】:
-s 参数:为虚拟机启动一个 gdbserver ,等待 gdb 客户端连接。默认 tcp 端口 1234 。
-S 参数:挂起虚拟机,直到 gdb 客户端连接并 给出继续执行的指令。 -
用 gdb 调试内核
前面终端中虚拟机处于挂起状态,我们要调试内核,必须要另外再开一个终端,通过tcp端口1234执行gdb调试,所以以下代码在另一个终端中进行。#新开一个终端,执行以下命令 cd ~/Desktop/linux #进入linux内核源码根目录 gdb vmlinux #以内核可执行文件作为参数运行 gdb target remote :1234 #连接至 gdbserver break start_kernel #使用break设置函数断点 break rest_init break kernel_init break run_init_process info breakpoints #查看所有设置的断点 continue #继续程序执行(遇到断点会停止运行)
-
添加断点成功后,即可开始调试
调试过程中,可以激活源码浏览窗口,查看执行位置附件的源码。
快捷键【Ctrl + x, a】
(重复这一操作可以反复隐藏/显示源码浏览窗口。)当内核程序运行至断点处时将暂停运行,在终端B的gdb调试环境中综合运用下列调试指令来跟踪调试内核程序 • step(单步执行,当执行函数调用时会跟踪进入函数内部) • next(单步执行,执行函数调用时不会跟踪进入函数内部) • finish(从一个函数内部返回到上一层调用它的地方) • continue(运行暂停的程序直到下一个断点处) • backtrace(查看当前正在调试的程序的函数调用栈)
-
调试内核,了解linux启动过程
-
正常调试截图
-
正常退出
1)先结束 qemu ,按
【ctrl+a,x】
,提示QEMU: Terminated
即为qemu退出成功
2)再退出 gdb ,在 gdb 所在终端,输入quit
回车即可。