Linux 下使用 qemu 运行树莓派
一、安装qemu
1、依赖安装
输入uname -a查看当前系统,根据系统运行依赖安装脚本即可从Linux上安装qemu。
Debian/Ubuntu apt-get install qemu
RHEL/CentOS yum install qemu-kvm
2、编译安装
wget https://download.qemu.org/qemu-3.1.1.tar.xz
tar xvJf qemu-3.1.1.tar.xz
cd qemu-3.1.1
./configure
make
make install
通过命令$ qemu-system-arm -M ? 可以获得qemu所支持的armv7设备
通过命令$ qemu-system-aarch64 -M ? 可以获得qemu所支持的armv8设备
二、下载树莓派镜像
这里首先需要明确交叉编译的程序是基于armV7 还是armV8 ,然后下载对应版本的镜像 https://www.raspberrypi.org/downloads/
0、查看镜像的分区
$ file 2018-06-27-raspbian-stretch.img
output:
2018-06-27-raspbian-stretch.img: DOS/MBR boot sector; partition 1 : ID=0xc, start-CHS (0x0,130,3), end-CHS (0x6,4,22), startsector 8192, 88472 sectors; partition 2 : ID=0x83, start-CHS (0x6,30,25), end-CHS (0x24a,106,32), startsector 98304, 9322496 sectors
1、从镜像拷贝出启动qemu所需的内核文件和设备树引导文件
从file命令的输出中,将 partition 1 'startsector'的值乘以512,并使用这个数字作为下面mount命令中的偏移值.(8192x512)
$ sudo mount 2018-06-27-raspbian-stretch.img -o offset=4194304 /mnt
[TODO] #从 /mnt 目录把镜像里的文件拷贝出来
$ sudo umount 2018-06-27-raspbian-stretch.img /mnt
其中kernel.img与kernel7.img,kernel8.img就是启动qemu所需的内核,*.dtd文件是设备树引导文件,对应树莓派的cpu及版本,其中kernel.img内核文件对应设备为:
kernel.img 对应 RPi 1B, 1A, A+, B+, 2B(第一版) Z, Z (摄像头版本), ZW, CM1
kernel7.img 对应 RPi2B2, RPi3B, CM3 and CM3L.
kernel8.img 对应 RPi3B, CM3 and CM3L, RPi4B,
qemu-system-arm 支持Raspberry Pi 2(2B)设备,所以对应该设备我们使用kernel7.img以及对应2B的bcm2709-rpi-2-b.dtb文件。
qemu-system-aarch64 支持Raspberry Pi 3(3B)设备,所以对应该设备我们使用kernel8.img以及对应3B的bcm2710-rpi-3-b.dtb文件。
2、将交叉编译好的执行程序放入镜像
从file命令的输出中,将 partition 2 'startsector'的值乘以512,并使用这个数字作为下面mount命令中的偏移值.(98304x512)
$ sudo mount 2018-06-27-raspbian-stretch.img -o offset=50331648 /mnt
[TODO] #将你交叉编译好的执行程序放入该目录下
$ sudo umount 2018-06-27-raspbian-stretch.img /mnt
3、如果镜像空间不足需要给镜像扩容
三、运行虚拟机
armV7:
qemu-system-arm -M raspi2 -kernel kernel7.img -sd 2018-06-27-raspbian-stretch.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait" -dtb bcm2709-rpi-2-b.dtb -nographic
armV8:
qemu-system-aarch64 -M raspi3 -kernel kernel8.img -sd 2020-08-20-raspios-buster-arm64-lite.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait" -dtb bcm2710-rpi-3-b.dtb -nographic
命令参数:
-M raspi2 模拟raspi2单板,你可以使用-M ?参数来获取该qemu版本支持的所有单板
-m 512M 单板运行物理内存512M
-kernel /path/to/kernel/dir/arch/arm/boot/zImage 告诉qemu单板运行内核镜像路径
-nographic 不使用图形化界面,只使用串口
-append "console=ttyAMA0" 内核启动参数,这里告诉内核vexpress单板运行,串口设备是哪个tty
如果搭建其它单板,需要注意内核启动参数的console=参数值,同样地,可从生成的.config文件中找到
树莓派默认用户名密码:(pi/raspberry)
qemu退出的方式:官方文档给出的是ctrl + A 和 X,需要注意ctrl 与 A同时按住抬起后再按X,不要三个键同时按~
*镜像扩容
1、查看现有树莓派镜像的空间
使用qemu-img的info命令:
qemu-img info 2018-06-27-raspbian-stretch.img
输出可以看到如下信息:
image: 2018-06-27-raspbian-stretch.img//img镜像名称
file format: raw//文件格式类型
virtual size: 4.6G (4919918592 bytes)//实际镜像文件大小
disk size: 4.6G//系统空间大小
2、对镜像文件进行扩展
使用qemu-img的resize命令
qemu-img resize 2018-06-27-raspbian-stretch.img +1G
再通过info命令检查当前镜像文件:
file format: raw
virtual size: 5.6G (5993660416 bytes)//实际镜像文件大小已经扩容1G空间
disk size: 4.6G
现在实际镜像文件已经扩容,但实际文件系统暂时还未识别已扩容的空间,需要对该虚拟分区进行格式化。
通过resize命令不仅可以扩展镜像大小,也可以对镜像进行裁剪,但裁剪之前需要对分区进行格式化并释放空间,否则裁剪时会损坏镜像。
每个树莓派镜像的分区默认有两个,sda1【boot分区】与sda2【linux分区】,此次扩容只对linux分区进行扩容。
3、启动镜像进入linux分区
扩展完毕后,进入镜像的linux系统中,通过df -h命令查看当前系统文件大小,可以看到当前系统还未识别新扩展的空间,可以看到linux分区几乎已经用光:
(/dev/sda2 会随运行命令root=/dev/mmcblk0p2 改变)
Filesystem Size Used Avail Use% Mounted on
/dev/root 4.5G 4.1G 98M 98% /
devtmpfs 124M 0 124M 0% /dev
tmpfs 124M 0 124M 0% /dev/shm
tmpfs 124M 1.9M 122M 2% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 124M 0 124M 0% /sys/fs/cgroup
/dev/sda1 41M 21M 21M 51% /boot
tmpfs 25M 0 25M 0% /run/user/1000
使用fdisk命令查看当前分区的起始位与结束位:sudo fdisk -l
Device Boot Start End Sectors Size Id Type
/dev/sda1 8192 93236 85045 41.5M c W95 FAT32 (LBA)
/dev/sda2 94208 9609215 9515008 4.6G 83 Linux
需要记录sda2(Linux分区)的start位置的sector。
使用fdisk对sda设备进行分区:sudo fdisk /dev/sda
操作如下:
****************************************************************************************************
* Welcome to fdisk (util-linux 2.29.2).
* Changes will remain in memory only, until you decide to write them.
* Be careful before using the write command.
*
*
* Command (m for help): d #删除分区指令
* Partition number (1,2, default 2): 2 #2即sda2分区
*
* Partition 2 has been deleted.
*
* Command (m for help): n #创建新分区
* Partition type
* p primary (1 primary, 0 extended, 3 free)
* e extended (container for logical partitions)
* Select (default p): p #创建主分区
* Partition number (2-4, default 2): 2 #创建sda2分区
* First sector (2048-11706367, default 2048): 94208 #输入sda2分区起始sector
* Last sector, +sectors or +size{K,M,G,T,P} (94208-11706367, default 11706367): 11706367 #默认镜像最后一个sector
*
* Created a new partition 2 of type 'Linux' and of size 5.6 GiB.
* Partition #2 contains a ext4 signature.
*
* Do you want to remove the signature? [Y]es/[N]o: N #此时已经扩展成功,选择不删除分区签名
*
* Command (m for help): w #保存此次操作
*
* The partition table has been altered.
* Calling ioctl() to re-read partition table.
* Re-reading the partition table failed.: Device or resource busy
*
* The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).
*
********************************************************************************************************
4、重启检查系统剩余空间
此时已经完成了对Linux分区的扩展,使用sudo reboot命令重启qemu。重启完成后使用resize2fs命令来时我们扩展的空间生效。
sudo resize2fs /dev/sda2
然后通过df -h命令来检查系统剩余空间:
Filesystem Size Used Avail Use% Mounted on
/dev/root 5.4G 4.1G 1.1G 80% /
devtmpfs 124M 0 124M 0% /dev
tmpfs 124M 0 124M 0% /dev/shm
tmpfs 124M 2.0M 122M 2% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 124M 0 124M 0% /sys/fs/cgroup
/dev/sda1 41M 21M 21M 51% /boot
tmpfs 25M 0 25M 0% /run/user/1000