当前位置: 首页 > news >正文

Linux学习——使用QEMU搭建ARM64环境

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_SUPPORT
	dst = 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);
		}
	}
#endif
	return 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.d

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
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时,不能成功打开图形化配置

按照提示添加需要的库

相关文章:

  • 【AI】基于多模态火车票数据提取
  • 【从零开始学习计算机科学】操作系统(六)内存管理
  • 卷积神经网络(笔记01)
  • leetcode:1629. 按键持续时间最长的键(python3解法)
  • Java 线程与线程池类/接口继承谱系图+核心方法详解
  • SpringBoot集成Swagger指南
  • 33.HarmonyOS NEXT NumberBox 步进器高级技巧与性能优化
  • 【时时三省】(C语言基础)赋值表达式和赋值语句和变量赋初值
  • TypeScript类:面向对象编程的基石
  • 关于 ESP32 未公开 Bluetooth® HCI 命令的事实澄清
  • [多线程]基于环形队列(RingQueue)的生产者-消费者模型的实现
  • c++20 Concepts的简写形式与requires 从句形式
  • 二叉树_3_模拟实现二叉树
  • PySide(PyQT),QGraphicsItem的pos()和scenePos()区别
  • 【数据分析大屏】基于Django+Vue汽车销售数据分析可视化大屏(完整系统源码+数据库+开发笔记+详细部署教程+虚拟机分布式启动教程)✅
  • Kotlin D3
  • 推理模型对SQL理解能力的评测:DeepSeek r1、GPT-4o、Kimi k1.5和Claude 3.7 Sonnet
  • H3C交换机的VRRP配置
  • Ansible运行原理揭秘:如何用YAML脚本掌控数服务器?
  • 第二篇:CTF常见题型解析:密码学、逆向工程、漏洞利用、Web安全
  • 遭“特朗普关税”冲击,韩国今年经济增长预期“腰斩”降至0.8%
  • 周启鸣加盟同济大学,曾任香港浸会大学深圳研究院院长
  • 美国三大指数全线高开:纳指涨逾4%,大型科技股、中概股大涨
  • 开局良好,我国第一季度广告业务收入保持较快增速
  • 丹麦召见美外交官,强调“不能容忍”美在格陵兰岛间谍活动
  • 人民日报评“组团退演出服”:市场经济诚信原则需全社会维护