qemu构建linux模拟环境

1.内核编译

内核编译是为了生成zImage文件。 我们通过编译vexpress_defconfig进行示例。

export PATH=$PATH:/opt/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4

编译内核需要关注两个产物,一个是内核产物zImage, 一个设备树产物*.dtb。

2.根文件系统制作

制作系统需要的根文件。

2.1 构建ext4文件

#创建ext4文件,并挂载好文件系统
    dd if=/dev/zero of=rootfs.ext4 bs=1M count=64
    mkfs.ext4 rootfs.ext4 -F
    sudo mkdir -p /mnt/temp
    sudo mount -t ext4 rootfs.ext4 /mnt/temp  #创建一个链接
    sudo cp -r ~/temp /mnt/temp #创建一些必要挂载文件

参考使用脚本生成基本的一些文件,驱动节点

#!/bin/bash
echo "------Create rootfs start...--------"

rootfs=rootfs_ext4
rm -rf $rootfs
mkdir $rootfs
cd $rootfs

echo "--------Create root,dev....----------"  
mkdir root dev etc boot tmp var sys proc lib mnt home usr
mkdir etc/init.d etc/rc.d

echo "make node in dev/console dev/null"
sudo mknod -m 600 dev/console c 5 1
sudo mknod -m 600 dev/null  c 1 3
sudo mknod -m 666 tty1 c 4 1 
sudo mknod -m 666 tty2 c 4 2 
sudo mknod -m 666 tty3 c 4 3 
sudo mknod -m 666 tty4 c 4 4

# create etc config /etc/inittab
echo -e "::sysinit:/etc/init.d/rcS " >etc/inittab
echo -e "::askfirst:-/bin/sh " >>etc/inittab
echo -e "::ctrlaltdel:/sbin/reboot " >>etc/inittab
echo -e "::shutdown:/bin/umount -a -r " >>etc/inittab

# create etc config /etc/init.d/rcs
echo -e "#! /bin/sh " >etc/init.d/rcS
echo -e "mount -t sysfs none /sys " >>etc/init.d/rcS
echo -e "mount -t proc none /proc " >>etc/init.d/rcS
echo -e "mount -t tmpfs tmpfs /tmp" >>etc/init.d/rcS
echo -e "mdev -s " >>etc/init.d/rcS
chmod +x etc/init.d/rcS

# create etc config /etc/fstab
echo -e "proc       /proc       proc        defaults 0 0 " >etc/fstab
echo -e "sysfs      /sys        sysfs       defaults 0 0 " >>etc/fstab
echo -e "devtmpfs   /dev        devtmpfs    defaults 0 0 " >>etc/fstab
echo -e "tmpfs      /tmp        tmpfs       defaults 0 0 " >>etc/fstab
echo -e "tmpfs      /var        tmpfs       defaults 0 0 " >>etc/fstab

echo "-------make rootfs done---------"

将生成的基本文件(init.d /dev下面文件)拷贝到挂载的rootfs.ext4

2.2 busybox配置最小文件系统

使用源码进行配置,编译

#参考脚本,导入交叉编译环境
export PATH=$PATH:/opt/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j16
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install

交叉编译完成,生成目录为 _install,可以将当前的内容拷贝到挂载的ext4文件 使用busybox备注: 1)end Kernel panic - not syncing: Requested init /linuxrc failed (error -2). 解决:busybox配置没有选择使用静态库,menuconfig阶段,选择上

Build BusyBox as a static binary (no shared libs)

2)end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. 解决:传递参数时,缺少指定init= 3.开始运行 3.1 安装配置好qemu后,开始进行模拟

sudo qemu-system-arm \
               -M vexpress-a9 \
               -m 512M \
               -kernel temp/zImage \
               -dtb temp/vexpress-v2p-ca9.dtb \
               -nographic \
               -append "root=/dev/mmcblk0 rw console=ttyAMA0 init=/linuxrc" \
               -sd temp/root.ext4

参数解释: -kernel 指定zImage 路径 -dtb 指定设备树 -append 传递给内核的参数列表,root路径,init进程路径 -sd sd卡,根文件系统路径