对于Linux爱好者,你是否也有这样的困惑,为了学习Linux而去选购高昂的开发版,这大可毋须,QEMU模拟器几乎可以满足你的需求linux最新内核5,足够你去学习Linux,它就能模拟出x86,arm,riscv等各类处理器构架linux获取当前时间,本文将向你呈现的不是QEMU/虚拟化的原理剖析,而是怎么搭建一个用于学习linux的QEMU环境,其实对于Linux内核的学习这早已足够了。
注意:本文基于最新的linux-5.9.2内核源代码,使用arm64的处理器构架,在ubuntu18.04系统上。
嵌入式进阶教程分门别类整理好了,看的时侯非常便捷,因为内容较多,这儿就截取一部份图吧。
须要的同事私信【内核】即可申领
1.交叉编译工具链的安装
工欲善其事必先利其器,搭建QEMU的模拟环境首先须要下载安装对应构架的交叉编译工具链(这儿是arm64构架):
注:有时侯须要安装一些依赖linux公社,按照提示安装即可!
$ sudo apt-get install gcc-aarch64-linux-gnu
安装完成以后查看版本说明安装完成:
$ aarch64-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=aarch64-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/aarch64-linux-gnu/5/lto-wrapper
Target: aarch64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 5.5.0-12ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libquadmath --enable-plugin --enable-default-pie --with-system-zlib --enable-multiarch --enable-fix-cortex-a53-843419 --disable-werror --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=aarch64-linux-gnu --program-prefix=aarch64-linux-gnu- --includedir=/usr/aarch64-linux-gnu/include
Thread model: posix
gcc version 5.5.0 20171010 (Ubuntu/Linaro 5.5.0-12ubuntu1)
2.QEMU的安装
下边安装我们的QEMU,其实我们可以下载QEMU的源码通过编译的形式安装,但这儿我们是直接apt-get的这些方法安装:
$ sudo apt-get install qemu-system-arm
安装完成以后同样查看版本号:
$ qemu-system-aarch64 --version
QEMU emulator version 4.2.0
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
说明安装成功!
3.根文件系统制做
这一步我们即将完成的是最小的根文件系统,即使是最小的根文件系统,并且我们还是希望才能运行动态编译的应用程序,具体的制做过程如下:
1)首先打算下载一份Busybox源码:
Busybox的官方源码下载路径为:
http://busybox.net/downloads/
这儿我们使用的是busybox-1.28.1:
2)解压源码
tar xvf busybox-1.28.1.tar.bz2
3)步入源码目录
cd busybox-1.28.1
4)指定工具链
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
5)配置
make menuconfig
静态编译:
Settings --->
[*] Build static binary (no shared libs)
6)编译安装
make
make install
7)建立其他目录结构
前面我们编译安装完成以后会在busybox源码目录的_install目录下生成必要的一些文件:
$ ls
bin linuxrc sbin usr
可以看见都是一些命令相关的文件早已作为init进程的linuxrc,缺乏其他的一些配置文件等目录,所以须要进一步构建。
我们来创建其他须要的目录:
mkdir dev etc lib sys proc tmp var home root mnt
我们主要须要更新etc、dev和lib目录:
1)对于etc目录的更新:
添加profile文件:
#!/bin/sh
export HOSTNAME=liebao
export USER=root
export HOME=/home
export PS1="[$USER@$HOSTNAME W]# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
可以看见我们自定义了命令提示符,cd步入了我们制订的目录homes,导入了环境变量。
添加inittab文件:
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
指定挂载的文件系统。
创建init.d目录:
mkdir init.d
init.d下添加rcS文件:
mkdir -p /sys
mkdir -p /tmp
mkdir -p /proc
mkdir -p /mnt
/bin/mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
到此我们etc下的文件都制做好了,目录结构如下:
$ tree
.
├── fstab
├── init.d
│ └── rcS
├── inittab
└── profile
1 directory, 4 files
2)制做dev下必要文件:
cd dev/
sudo mknod console c 5 1
3)制做lib下必要文件:
为了支持动态编译的应用程序的执行,根文件系统须要支持动态库,所以我们添加arm64相关的动态库文件到lib下:
cd lib
cp /usr/aarch64-linux-gnu/lib/*.so* -a .
对库文件进行减肥(除去符号表和调试信息),致使库文件变小:
aarch64-linux-gnu-strip *
至此,我们的最小的文件系统早已全部制做完成!
4.内核源码的编译
1)下载最新的Liunx内核源码:
官网下载最新的Linux-5.9.2内核:
301MovedPermanently
2)解压、
tar xvf linux-5.9.2.tar.xz
3)放置文件系统到源码目录:
cd linux-5.9.2
cp ../../busybox-1.31.1/_install _install_arm64 -a=
4)配置
添加hotplug支持:
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 6d04b9577..f89143b69 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1043,3 +1043,6 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y
+
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
添加initramfs的支持:
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f89143b69..caa7a34bf 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1046,3 +1046,5 @@ CONFIG_MEMTEST=y
CONFIG_UEVENT_HELPER=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+
+CONFIG_INITRAMFS_SOURCE="_install_arm64"
4)编译
现今进行漫长的编译过程,编译得快慢取决于笔记本的性能:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make defconfig
make all -j8
5.开始体验
1)创建共享目录
$ mkdir kmodules
用于主机和qemu运行的系统进行共享文件。
2)运行qemu模拟器:
qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt
-m 1024 -smp 4 -kernel arch/arm64/boot/Image --append "rdinit=/linuxrc root=/dev/vda rw console=ttyAMA0 loglevel=8" -nographic
--fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none
-device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount
其中:-cpu指定了模拟的cpu为cortex-a57,-m1024指定显存大小为1G,-smp4指定模拟的系统为4核处理器linux最新内核5,-kernel指定启动的内核镜像,--append指定传递的命令行参数,旁边的选项指定共享目录早已使用的9P合同。
运行上去以后就步入了跟文件系统:
Please press Enter to activate this console.
[root@liebao ]#
[root@liebao ]#
[root@liebao ]#
[root@liebao ]# uname -a
Linux (none) 5.9.2-gacff57f0a #1 SMP PREEMPT Sat Oct 31 11:03:25 CST 2020 aarch64 GNU/Linux
可以看见内核版本是我们编译的新的Linux-5.9.2内核,四处我们成功搭建了QEMU环境来运行我们的新内核。
3)使用模拟c盘
里面我们使用initramfs的形式将我们的文件系统的目录直接打包到内核源码,成为了内核的一部份,其实这个时侯可以操作文件,并且文件都是在显存中,系统重启都会遗失,所以下边我们使用模拟c盘的形式来挂载根文件系统。
制做c盘文件:
dd if=/dev/zero of=rootfs_ext4.img bs=1M count=8192
mkfs.ext4 rootfs_ext4.img
mkdir -p tmpfs
mount -t ext4 rootfs_ext4.img tmpfs/ -o loop
cp -af _install_arm64/* tmpfs/
umount tmpfs
rm -rf tmpfs
chmod 777 rootfs_ext4.img
执行qemu命令:
qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt
-m 1024 -smp 4 -kernel arch/arm64/boot/Image --append "noinitrd root=/dev/vda rw console=ttyAMA0 loglevel=8" -nographic
-driver if=none,file=rootfs_ext4.img,id=hd0
-device virtio-blk-device,drive=hd0
--fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none
-device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount
我们可以发觉,传递给内核的命令行参数变化了,添加了noinitrd选项,这样才会挂载我们自己的模拟c盘。