上海高端室内设计公司seo外包多少钱
Linux学习——使用QEMU搭建ARM64环境
文章目录
- Linux学习——使用QEMU搭建ARM64环境
- 一、了解QEMU
- 二、安装QEMU虚拟机
- 1、安装 QEMU虚拟机
- 2、创建虚拟硬盘
- 3、效果展示
- 三、安装交叉编译环境
- 四、了解根文件系统
- 五、创建基于 Ubuntu Linux 的根文件系统
- 1、下载busybox1.36.0:
- 2、制定编译工具链
- 3、配置BusyBox
- 4、编译busybox
- 5、创建需要的目录
- 六、下载内核kernel
- 1、下载内核kernel压缩包
- 2、指定编译工具
- 3、将根文件系统放到源码根目录
- 4、配置生成.config
- 5、配置支持
- 6、编译
- 七、启动QEMU虚拟机
- 八、QEMU虚拟机的其他使用方法
- 九、编译一个简单的内核模块并在QEMU上运行
- 1、创建文件
- 2、在编写Makefile文件
- 3、编译
- 4、启动QEMU
- 5、结果
- 出现问题
一、了解QEMU
两种工作模式:全系统模拟系统
用户模式
本质工作:二进制翻译
设备的基本模式:backend+device
硬件加速支持:KVM
二、安装QEMU虚拟机
1、安装 QEMU虚拟机
打开虚拟机的命令行,并输入一下代码
sudo apt update
sudo apt install qemu-utils //用于网络桥接的工具
qemu-img --version //确认是否安装成功
sudo apt install qemu qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager
//qemu-kvm 是QEMU和KVM之间的集成模块
//libvirt-daemon-system libvirt-clients管理虚拟化平台的开源API。守护进程和工具集合
//bridge-utils提供了用于网络桥接的工具
//Virtual Machine Manager (Virt-Manager) 是一个图形界面应用程序,用于管理虚拟机
2、创建虚拟硬盘
qemu-img create -f qcow2 ubuntu.qcow2 20G //创建虚拟硬盘
ls -lh unbuntu.qcow2 //检查创建是否成功
3、效果展示
可在虚拟机的home文件中找到ubuntu.qcow2文件
三、安装交叉编译环境
sudo apt-get install gcc-aarch64-linux-gnu //下载交叉编译工具
sudo apt-get install libncurses5-dev build-essential git bison flex libssl-dev
sudo apt install qemu-system-arm
四、了解根文件系统
Linux的根文件系统一般也叫做 rootfs,Linux的根文件系统更像是一个文件夹或者叫做目录,在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文件,这些文件是Linux运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。
根文件系统的“根”字就说明了这个文件系统的重要性,它是其他文件系统的根,没有这个“根” ,其他的文件系统或者软件就别想工作。比如我们常用的 ls、mv、ifconfig 等命令其实就是一个个小软件,只是这些软件没有图形界面,而且需要输入命令来运行。这些小软件就保存在根文件系统中。
在构建根文件系统之前,先来看一下根文件系统里面都有些什么内容,根文件系统的目录名字为‘/’ ,就是一个斜杠。下面以Ubuntu为例,一些常用的子目录介绍如下表示:
五、创建基于 Ubuntu Linux 的根文件系统
1、下载busybox1.36.0:
wget http://www.busybox.net/downloads/busybox-1.36.0.tar.bz2 //下载tar -vxjf busybox-1.36.0.tar.bz2 //解压ls ~/busybox-1.36.0//查看解压文件
2、制定编译工具链
cd busybox-1.36.0
export ARCH=arm64
//设置ARCH环境变量为arm64
//这个变量告诉编译器我们正在为目标架构arm64(即64位ARM架构)进行编译
export CROSS_COMPILE=aarch64-linux-gnu-
//设置CROSS_COMPILE环境变量为aarch64-linux-gnu-
//这个变量指定了交叉编译工具链的前缀。在这里,我们使用的是针对arm64架构的GNU交叉编译工具链echo $ARCH //检测ARCH环境变量是否配置成功,输出"arm64"
echo $CROSS_COMPILE //检测CROSS_COMPILE环境变量是否配置成功,输出"aarch64-linux-gnu-"
3、配置BusyBox
busybox中文字符支持:若直接编译busybox,使用串口工具时是不支持中文显示的,会显示为“?” ,可修改源码,取消 busybox对中文显示的限制
打开文件/libbb/printable_string.c,将函数printable_string()中的部分程序注释掉,修改后的函数内容如下:
/* vi: set sw=4 ts=4: */
/** Unicode support routines.** Copyright (C) 2010 Denys Vlasenko** Licensed under GPLv2, see file LICENSE in this source tree.*/
#include "libbb.h"
#include "unicode.h"const char* FAST_FUNC printable_string2(uni_stat_t *stats, const char *str)
{char *dst;const char *s;s = str;while (1) {unsigned char c = *s;if (c == '\0') {/* 99+% of inputs do not need conversion */if (stats) {stats->byte_count = (s - str);stats->unicode_count = (s - str);stats->unicode_width = (s - str);}return str;}if (c < ' ')break;//if (c >= 0x7f)// break;s++;}#if ENABLE_UNICODE_SUPPORTdst = unicode_conv_to_printable(stats, str);
#else{char *d = dst = xstrdup(str);while (1) {unsigned char c = *d;if (c == '\0')break;//if (c < ' ' || c >= 0x7f)if (c < ' ')*d = '?';d++;}if (stats) {stats->byte_count = (d - dst);stats->unicode_count = (d - dst);stats->unicode_width = (d - dst);}}
#endifreturn auto_string(dst);
}const char* FAST_FUNC printable_string(const char *str)
{return printable_string2(NULL, str);
}
接着打开文件/libbb/unicode.c,修改如下内容:
//在unicode.c的1011到1058之间
static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char *src, unsigned width, int flags)
{char *dst;unsigned dst_len;unsigned uni_count;unsigned uni_width;if (unicode_status != UNICODE_ON) {char *d;if (flags & UNI_FLAG_PAD) {d = dst = xmalloc(width + 1);while ((int)--width >= 0) {unsigned char c = *src;if (c == '\0') {do*d++ = ' ';while ((int)--width >= 0);break;}//*d++ = (c >= ' ' && c < 0x7f) ? c : '?';*d++ = (c >= ' ' ) ? c : '?';src++;}*d = '\0';} else {d = dst = xstrndup(src, width);while (*d) {unsigned char c = *d;//if (c < ' ' || c >= 0x7f)if (c < ' ')*d = '?';d++;}}if (stats) {stats->byte_count = (d - dst);stats->unicode_count = (d - dst);stats->unicode_width = (d - dst);}return dst;}dst = NULL;uni_count = uni_width = 0;dst_len = 0;while (1) {int w;wchar_t wc;
安装需要的开发库
sudo apt update
sudo apt install make
sudo apt install make-guile
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev
配置选项
make defconfig #使用默认配置
make menuconfig #打开图形化配置界面
设置setting-> Build static binary (no shared libs)
设置Settings -> Support Unicode,使能busybox的unicode编码以支持中文
4、编译busybox
make
make install CONFIG_PREFIX=~/linux/rootfs
#CONFIG_PREFIX指定编译结果的存放目录
ls ~/linux/rootfs
//打开rootfs文件,新增了bin linuxrc sbin usr这些文件
5、创建需要的目录
cd init.dmkdir -p /sys
mkdir -p /tmp
mkdir -p /proc
mkdir -p /mnt
/bin/mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
mev -s
六、下载内核kernel
1、下载内核kernel压缩包
Liunx下载地址
tar xvf linux-6.13.6.tar.xz//解压
2、指定编译工具
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
3、将根文件系统放到源码根目录
cd linux-6.13.6
sudo cp ~/linux/rootfs rootfs_arm64 -a
4、配置生成.config
make defconfig
make menuconfig
5、配置支持
添加hotplug支持
Device Drivers->Generic Driver Options-> Support for uevent helper (/sbin/hotplug) path to uevent helper
添加initramfs支持
General setup —>[*]Initial RAM filesystem and RAM disk(initramfs/initrd) support
(_install_arm64) Initramfs souce file(s)
Virtual address space配置
Kernel Features —> Page size(4KB) —>Virtual address space size(48-bit)
6、编译
make all -j8
七、启动QEMU虚拟机
1)配置虚拟机属性
qemu-system-x86_64 \
-drive if=virtio,file=ubuntu.qcow2,format=qcow2 \
-cdrom ~/Downloads/ubuntu-20.04.6-live-server-amd64.iso \
-m 2048 \
-boot order=d
2)启动虚拟机
qemu-system-x86_64 -hda /home/sunrise/ubuntu.qcow2 -cdrom /home/sunrise/Downloads/ubuntu-20.04.6-live-server-amd64.iso -m 2048 -boot d
//ubuntu-20.04.6-live-server-amd64.iso可替换成你在虚拟机中所下载的ubuntu镜像名称
如果在过程中鼠标消失可按ctrl+aly+G
3)启动后需要等待两个阶段
4)等待过后会出现引导性的指示
5)若点击继续会格式化所选磁盘
八、QEMU虚拟机的其他使用方法
1)打开后选择监视器
2)在命令中输入help
,可以显示当前虚拟机的信息
九、编译一个简单的内核模块并在QEMU上运行
1、创建文件
在根目录下创建一个文件夹module_test,并编写一个简单的hello.c代码
// 包含内核模块编程所需的头文件
#include <linux/init.h> // 包含模块初始化和退出函数的宏
#include <linux/module.h> // 包含模块相关的宏和函数
#include <linux/kernel.h> // 包含内核打印函数 printk 的头文件// 模块初始化函数
// 当模块被加载到内核时,此函数会被调用
static int __init test_init(void)
{// 在内核日志中打印 "hello world!"printk("hello world!\n");// 返回 0 表示初始化成功return 0;
} // 模块退出函数
// 当模块从内核中卸载时,此函数会被调用
static void __exit test_exit(void)
{// 在内核日志中打印 "hello exit!"printk("hello exit!\n");
}// 注册模块的初始化函数
// 当模块被加载时,test_init 函数会被调用
module_init(test_init);// 注册模块的退出函数
// 当模块被卸载时,test_exit 函数会被调用
module_exit(test_exit);// 声明模块的许可证
// GPL 是 GNU 通用公共许可证,表示这是一个开源模块
MODULE_LICENSE("GPL");
2、在编写Makefile文件
# 设置目标架构为 ARM64
export ARCH=arm64# 设置交叉编译工具链前缀为 aarch64-linux-gnu-
export CROSS_COMPILE=aarch64-linux-gnu-# 定义内核源码目录
KERNEL_DIR ?= /home/xlq/linux-6.13.5# 定义要编译的内核模块目标文件
# obj-m 表示将 hello.c 编译为内核模块 hello.ko
obj-m := hello.o# 默认目标:编译内核模块
modules:# 调用内核源码目录的 Makefile,编译当前目录下的模块$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules# 清理目标:删除编译生成的文件
clean:# 调用内核源码目录的 Makefile,清理当前目录下的生成文件$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean# 安装目标:将编译好的内核模块复制到指定目录
install:# 将当前目录下所有的 .ko 文件复制到内核源码目录的 kmodules 子目录中cp *.ko $(KERNEL_DIR)/kmodules
3、编译
编译module,拷贝到共享目录
make modules
make install
4、启动QEMU
qemu-system-x86_64 -hda /home/sunrise/ubuntu.qcow2 -cdrom /home/sunrise/Downloads/ubuntu-20.04.6-live-server-amd64.iso -m 2048 -boot d
5、结果
出现问题
1、MENU打开虚拟机没有反应
退出后重新配置虚拟机属性
2、在配置busybox时,不能成功打开图形化配置
按照提示添加需要的库