QEMU是一種純軟件實現的虛擬化模擬器,幾乎能夠模擬全部硬件,包括咱們本次要用的ARM A9平臺。它的原理是將guest架構代碼轉換爲TCG中間代碼,再轉換爲host架構代碼。linux
虛擬機:ubuntu18.04 LTSexpress
sudo apt install gcc-arm-linux-gnueabi
安裝完成後,咱們能夠看一下該工具鏈支持的目標架構:ubuntu
arm-linux-gnueabi-gcc --target
翻一下結果能夠看到:架構
Known ARM CPUs (for use with the -mcpu= and -mtune= options): arm1020e arm1020t arm1022e arm1026ej-s arm10e arm10tdmi arm1136j-s arm1136jf-s arm1156t2-s arm1156t2f-s arm1176jz-s arm1176jzf-s arm2 arm250 arm3 arm6 arm60 arm600 arm610 arm620 arm7 arm70 arm700 arm700i arm710 arm7100 arm710c arm710t arm720 arm720t arm740t arm7500 arm7500fe arm7d arm7di arm7dm arm7dmi arm7m arm7tdmi arm7tdmi-s arm8 arm810 arm9 arm920 arm920t arm922t arm926ej-s arm940t arm946e-s arm966e-s arm968e-s arm9e arm9tdmi cortex-a12 cortex-a15 cortex-a15.cortex-a7 cortex-a17 cortex-a17.cortex-a7 cortex-a32 cortex-a35 cortex-a5 cortex-a53 cortex-a57 cortex-a57.cortex-a53 cortex-a7 cortex-a72 cortex-a72.cortex-a53 cortex-a73 cortex-a73.cortex-a35 cortex-a73.cortex-a53 cortex-a8 cortex-a9 cortex-m0 cortex-m0.small-multiply cortex-m0plus cortex-m0plus.small-multiply cortex-m1 cortex-m1.small-multiply cortex-m23 cortex-m3 cortex-m33 cortex-m4 cortex-m7 cortex-r4 cortex-r4f cortex-r5 cortex-r7 cortex-r8 ep9312 exynos-m1 fa526 fa606te fa626 fa626te fa726te fmp626 generic-armv7-a iwmmxt iwmmxt2 marvell-pj4 mpcore mpcorenovfp native strongarm strongarm110 strongarm1100 strongarm1110 xgene1 xscale
支持的arch和CPU很是全,也支持咱們此次將要模擬的cortex-a9;甚至也支持cortex-m,也就能夠編譯無MMU的單片機的內核和應用。app
sudo apt install qemu
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install
至此,在busybox目錄下生成了'_intall' 目錄,將做爲咱們構建根文件系統的目錄,在根文件系統目錄下補充一些內容。
增長如下目錄:dom
a. dev目錄下靜態建立以下節點:工具
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 sudo mknod -m 666 console c 5 1 sudo mknod -m 666 null c 1 3
console 和 null 是必須的,若是沒有則會報錯。
b. etc/inittab 文件內容以下,可參考busyboxdir/examples/inittab編寫:oop
::sysinit:/etc/init.d/rcS ::askfirst:/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r ::restart:/sbin/init tty2::askfirst:/bin/sh tty3::askfirst:/bin/sh tty4::askfirst:/bin/sh
c. etc/fstab 文件內容以下,主要目的是指明一些文件系統掛載點:測試
#device mount-point type option dump fsck order proc /proc proc defaults 0 0 temps /tmp rpoc defaults 0 0 none /tmp ramfs defaults 0 0 sysfs /sys sysfs defaults 0 0 mdev /dev ramfs defaults 0 0
d. etc/init.d/rcS 文件內容以下,inittab第一條指明瞭從rcS中去執行腳本ui
mount -a echo "/sbin/mdev" > /proc/sys/kernel/hotplug /sbin/mdev -s # 根據/etc/mdev.conf中的配置進行生成設備節點 mount -a
順便修改rcS的權限:
chmod 777 etc/init.d/rcS
e. lib 文件拷貝,由於busybox咱們採用默認的動態連接(建議),這樣能夠節省根文件系統大小,由於應用也能夠連接相應的庫。首先經過下邊3條命令任意一條查看busybox依賴的庫文件。
arm-linux-readelf -d busybox | grep NEEDED arm--linux-objdump -x busybox | grep NEEDED strings busybox | grep ^lib
注意:ld-linux.so.3有時候不會顯示,咱們也必須拷貝它,若是之後編譯應用程序,咱們也要查看依賴的庫,補足根文件系統中缺乏的庫文件。
cp /usr/arm-linux-gnueabi/lib/ld-linux.so.3 _install/lib/ cp /usr/arm-linux-gnueabi/lib/libc.so.6 _install/lib/ cp /usr/arm-linux-gnueabi/lib/libm.so.6 _install/lib/ cp /usr/arm-linux-gnueabi/lib/libresolv.so.2 _install/lib/
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig(option) make
將 zImage dtb文件拷貝出來,方便使用。 若是已經咱們已經開發了一些驅動,須要進行測試,除了將ko文件拷貝到根文件系統中,也應該執行模塊安裝命令,不然modules依賴關係,參數、符號等沒法使用。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install INSTALL_MOD_PATH=busybox-dir/_install/
執行完成後,將在根文件系統的lib下建立modules目錄。
dd if=/dev/zero of=rootfs.ext3 bs=1M count=32
將該空白文件格式化爲ext3格式(內核默認支持文件系統,若是使用其餘須要配置內核):
mkfs.ext3 rootfs.ext3
將該空白文件,掛載在一個目錄下:
mkdir fs sudo mount -o loop rootfs.ext3 ./fs
將busybox構建的根文件系統拷貝到掛載點下,而後再卸載
sudo cp -rf busybox-dir/_install/* ./fs sudo umount ./fs
qemu-system-arm \ -M vexpress-a9 \ -kernel ./zImage \ -nographic \ -m 512M \ -smp 4 \ -sd ./rootfs.ext3 \ -dtb vexpress-v2p-ca9.dtb \ -append "init=/linuxrc root=/dev/mmcblk0 rw rootwait earlyprintk console=ttyAMA0"
上述腳本,-M 指定了目標板, -kernel 指定了linux內核鏡像, -nographic 指定無圖形顯示,-m 512M指定了運行內存大小,-smp 指定4核, -sd 指定了外部有1個sd卡,卡內是rootfs.ext3鏡像文件, -dtb 指定了設備樹文件, -append 指定了bootargs; bootargs中init=/linuxrc 指定了init進程是根文件系統下的linuxrc(busybox生成), root=/dev/mmcblk0 指定了根文件系統爲sd卡, console指定了ttyAMA0,即控制檯。
Booting Linux on physical CPU 0x0 Linux version 4.19.86 (yhangzzz@yhangzzz-virtual-machine) (gcc version 7.4.0 (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1)) #2 SMP Sun Dec 1 13:35:37 CST 2019 CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache OF: fdt: Machine model: V2P-CA9 Memory policy: Data cache writealloc random: get_random_bytes called from start_kernel+0x98/0x474 with crng_init=0 percpu: Embedded 16 pages/cpu s32780 r8192 d24564 u65536 Built 1 zonelists, mobility grouping on. Total pages: 130048 Kernel command line: init=/linuxrc root=/dev/mmcblk0 rw rootwait earlyprintk console=ttyAMA0 log_buf_len individual max cpu contribution: 4096 bytes ... ... ... EXT4-fs (mmcblk0): mounting ext3 file system using the ext4 subsystem random: fast init done EXT4-fs (mmcblk0): recovery complete EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null) VFS: Mounted root (ext3 filesystem) on device 179:0. Freeing unused kernel memory: 1024K Run /linuxrc as init process random: crng init done mount: mounting temps on /tmp failed: No such device Please press Enter to activate this console. /bin/sh: can't access tty; job control turned off / # ls bin etc lib lost+found sbin tmp dev home linuxrc proc sys usr / #
本文中,使用qemu搭建了arm-a9的虛擬化平臺,用於linux內核開發、驅動開發、根文件系統構建、應用開發,或者uboot開發。雖然是虛擬的,可是和實際開發中的步驟基本一致。