记得自己第一次编译内核代码的时候,很是傻逼,已经是4年前的事了,来到了新公司发现真的好久没有做内核方面的工作了,有点小小的忧伤,最近在看virio的一些文章,决定自己今后每周都要写一些关于内核的知识,作为对自己的鼓励吧。
目录结构: 1:内核源码编译 2:qemu 源码编译
3:构建initramfs根文件系统
4: 最基本的调试方法
一:内核源码:
原理性的东西,网上一大堆,我这里只是讲一下从github上下载源码,打补丁,到编译vmlinx debug-info的过程。
1:下载内核源码,我们以4.15为例:
wget --no-check-certificate https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.14.105.tar.gz
2:安装依赖的工具
yum install -y openssl-devel bison flex bc elfutils-libelf-devel centos-release-scl yum install -y devtoolset-7-gcc* source /opt/rh/devtoolset-7/enable
3: 打上自己的补丁: 解压linux-4.14.105.tar.gz 打上自己的补丁。
$ tar xzvf linux-4.14.105.tar.gz $ tar xzvf patches.tar.gz $ cd linux-4.14.105/ $ ls -1 ../patches using below CMD. $ patch -p1 < ../patches/"patch_name"
3: 生成config文件,修改文件
这一步有很多的方法,但是我发现最简单的也最好用的方式,就是直接将出问题的环境上的config直接copy过来,进行就该就可以。
cp /boot/config-4.14.105-abcdef+ ./x86_64_defconfig 修改CONFIG_DEBUG_INFO=y 支持debug
4:可以用rpm 工具编译成rpm包也可以直接生成vmlinux使用
$make x86_64_defconfig #生成.config 1:直接编译 make -j$(nproc) //for example: make -j60 2:或者编译成rpm包 $ make rpm-pkg -j$(nproc)
[root@localhost linux-4.14.105]# file vmlinux
vmlinux: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=ee3e575977c8acafeacd3c2aac38bf7b096499ea, not stripped
二:编译可以调试的qemu
1:编译qemu
下载源码 下载地址
wget https://download.qemu.org/qemu-4.0.0.tar.xz
安装依赖包
yum -y install gcc gcc-c++ automake libtool zlib-devel glib2-devel bzip2-devel libuuid-devel spice-protocol spice-server-devel usbredir-devel libaio-devel SDL2-devel
编译安装
tar xvJf qemu-4.0.0.tar.xz
cd qemu-4.0.0
../configure --enable-kvm --enable-debug --enable-vnc --enable-werror --target-list="x86_64-softmmu"
make -j$(nproc)
默认安装在/usr/local/bin/ 编译完成之后 做链接
ln -s /usr/local/bin/qemu-system-x86_64 /usr/bin/qemu-kvm
ln -s /usr/local/bin/qemu-system-x86_64 /usr/libexec/qemu-kvm
ln -s /usr/local/bin/qemu-img /usr/bin/qemu-img
查看当前qemu版本
qemu-img --version
qemu-kvm --version
三、构建initramfs根文件系统
Linux系统启动阶段,boot loader加载完内核文件vmlinuz后,内核紧接着需要挂载磁盘根文件系统,但如果此时内核没有相应驱动,无法识别磁盘,就需要先加载驱动,而驱动又位于/lib/modules
,得挂载根文件系统才能读取,这就陷入了一个两难境地,系统无法顺利启动。于是有了initramfs根文件系统,其中包含必要的设备驱动和工具,boot loader加载initramfs到内存中,内核会将其挂载到根目录/
,然后运行/init
脚本,挂载真正的磁盘根文件系统。
1:下载 busybox https://busybox.net/ 下载并解压源码 2:编译busybox源码 2.1 make defconfig&&make menuconfig 2.2 选择编译为静态库 -> Build Options [*] Build BusyBox as a static binary (no shared libs) 3:编译 make -j4 4: 安装 sudo make install 5:此时可以在busybox-1.32.0/中看到生成的_install目录。通过下面的命令可以验证busybox是否安装正确 [root@localhost busybox-1.32.0]# ./busybox ls 6: 制作自己的initrd 6.1:mkdir ramdisk && cd ramdisk && cp -r ../busybox-1.32.0/_install/* . 6.2:ln -s bin/busybox init 6.3:mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin},dev} 创建/ 目录下的文件夹 6.4: 创建 inittab文件 chmod +x etc/inittab cat etc/inittab ::sysinit:/etc/init.d/rcS ::askfirst:-/bin/sh ::restart:/sbin/init ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a 6.5:创建/etc/init.d/rcS 文件 mkdir init.d && cd init.d && vim rcS #!/bin/sh mount proc mount -o remount,rw / mount -a clear echo "My Tiny Linux Start :D ......" 6.6:创建 etc/fstab # /etc/fstab proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 devtmpfs /dev devtmpfs defaults 0 0 6.7 生成 initrd cd ramdisk && find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.img
7: 验证一下:qemu-kvm -kernel /root/rpmbuild/BUILD/kernel-4.14.105/arch/x86_64/boot/bzImage -initrd initramfs.img -smp 4 -m 4096 -enable-kvm -append "console=ttyS0" -nographic
四: 最简单的基本的调试方式
1:假设,你已经制作好了自己的qcow2文件,有一个可以启动的镜像文件(TODO:要写一个)
qemu-kvm -kernel linux-4.14.105/arch/x86_64/boot/bzImage -initrd initramfs.img -smp 4 -m 4096 -enable-kvm -append "console=ttyS0" -nographic -S -s
注意这个地方有两个点要关注
1: -S 就是挂起gdbserver,让gdb remote connect it。
-s 默认使用1234端口进行远程调试,和-gdb tcp::1234类似
2:hb xxxx 主要是设置硬件断点,普通的b xxx 有时 gdb 停不下来。
说道这里,基本上已经可以做简单的内核的代码跟踪了,但是还是解决不了我们的 gdb virtio的问题。原因是这样的,我们启动的内核没有vitio的设备, 还有就是我们这样是没有vitio的驱动。所以还是不行。应该怎么做呢? 鉴于篇幅太长了,可能看着看着就烦了,所以我在下一篇文章中说明。
>>>>>>>>平常心,不在浮沙上筑高台,阳光总在风雨后<<<<<<<<
参考文章:https://blog.csdn.net/jasonLee_lijiaqi/article/details/80967912
原文:https://www.cnblogs.com/piaomiaofeixue/p/13975627.html