x86版Ubuntu的容器中运行ARM版Ubuntu

昨天尝试了一下x86版的ubuntu上使用qemu运行arm版ubuntu,使用起来感觉比较慢,毕竟是需要qemu模拟运行整个操作系统。

于是笔者想是否可以在x86版Ubuntu的容器中运行ARM版Ubuntu,经过查询资料,发现还真是完全可行的,它通过 binfmt_misc + QEMU 用户态模拟 技术实现,不得不赞叹Linux系统的强大

它的核心原理

  1. binfmt_misc (Binary Format Miscellaneous):
    这是 Linux 内核的一个功能,允许内核识别并处理特定格式(通过文件开头的"魔数"识别)的可执行文件。当内核遇到一个它本身不支持的架构(如 ARM)的可执行文件时,binfmt_misc 可以配置成调用一个指定的用户空间程序(这里是 QEMU)来执行它。
  2. QEMU User Emulation:
    QEMU 的 用户态模拟 模式允许它在一种 CPU 架构(宿主机的 x86)上运行为另一种 CPU 架构(容器的 ARM)编译的程序。它动态地将目标架构(ARM)的指令翻译成宿主机架构(x86)的指令来执行。这个过程不需要模拟整个操作系统内核,效率相对较高(虽然仍有性能损失)。

一、宿主环境准备

需要在宿主Ubuntu系统中安装qemu-user-staticbinfmt-support

bash 复制代码
sudo apt install qemu-user-static binfmt-support

二、拉取ARM版ubuntu容器镜像

bash 复制代码
$ docker pull --platform linux/arm64 ubuntu:24.04
24.04: Pulling from library/ubuntu
3eff7d219313: Pull complete 
Digest: sha256:a328b84b92f71a85f459722a1c73c0363f9f8e3f66bf74a204bb35c605cf670c
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.04

三、创建容器

参见笔者之前的博文:搭建ubuntu容器内C/C++开发调试环境

bash 复制代码
$ sudo docker run -itd -p 2822:22 --privileged --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=SYS_ADMIN --name ubuntua ubuntu:24.04 bash
WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64/v4) and no specific platform was requested
d56837424fa8ef161d7c463e50bdb0288340d7797348fbfd2a4acfdae50ccc87

创建容器比使用qemu安装ARM版Ubuntu快多了,创建好容器之后,使用下面的命令进入容器,并确认是否为ARM版,aarch64为ARM64,说明能正常运行。

bash 复制代码
$ $ docker exec -it ubuntua bash
root@d56837424fa8:/# uname -m
aarch64

后续参见笔者之前的博文:搭建ubuntu容器内C/C++开发调试环境,在容器中安装openssh-server,并让容器启动时自动运行openssh-server,以及安装编译器等等。

bash 复制代码
root@d56837424fa8:/# apt update
root@d56837424fa8:/# apt install gcc gdb cmake ninja-build openssh-server
root@d56837424fa8:/# mkdir /run/sshd
root@d56837424fa8:/# /usr/sbin/sshd&
root@d56837424fa8:/# adduser admin

注意:如果想要在容器中使用GDB进行调试程序,将会出现问题,导致无法调试

bash 复制代码
warning: Could not trace the inferior process.
warning: ptrace: Function not implemented
During startup program exited with code 127.

即使我们在创建容器时,添加了参数:

bash 复制代码
--privileged --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=SYS_ADMIN

依旧无法使用GDB调试程序,原因是在x86系统中运行arm容器,是通过QEMU 的 用户态模拟 模式来运行的,目前QEMU 用户态模拟无法完全支持 ptrace 系统调用的跨架构调试,ptrace 需要与内核深度交互,而QEMU 用户态模拟无法正确传递所有 ptrace 系统调用,特别是涉及寄存器访问和内存操作等调试功能。

据说可以通过使用相同版本的gdb-multiarchgdbserver进行远程调试,笔者没有尝试是否行得通,读者可以自行尝试。其方法是在容器内使用:

bash 复制代码
gdbserver :1234 ./demo

进行监听,需要将容器内的1234端口映射到宿主机的某个端口,比如还是1234

然后将要调试的程序复制到宿主机中,在宿主机中使用相同版本的gdb-multiarch调试

bash 复制代码
gdb-multiarch -ex "set architecture aarch64" -ex "target remote 127.0.0.1:1234" -ex "file demo"

这种方法适用于命令行调试,不太适合VSCode这样的IDE,不太方便。

综上,容器中运行ARM系统最大的好处就是比模拟整个ARM系统快,缺点就是不能直接在容器中使用GDB进行调试。如果要进行ARM的C/C++开发,为了方便调试,还是使用前文x86版的ubuntu上使用qemu运行arm版ubuntu介绍的模拟整个系统吧。

如果对你有帮助,欢迎点赞收藏!

相关推荐
石头53012 分钟前
Service 详解
linux
小鸡脚来咯13 分钟前
Linux 服务器问题排查指南(面试标准回答)
linux·服务器·面试
末日汐16 分钟前
磁盘与文件系统
linux·运维·数据库
爱吃大芒果18 分钟前
openJiuwen(Windows端)大模型添加及AI Agent创建教程
人工智能·ubuntu·openjiuwen
水天需01023 分钟前
Linux PS4 环境变量详解
linux
小新ya33 分钟前
vscode增删改查文件,一直等待中...
linux·vscode
牛奔1 小时前
Docker Compose 解决服务间 DNS 解析失败问题
运维·docker·容器
济6171 小时前
linux(第十四期)--官方 SDK 移植实验-- Ubuntu20.04
linux·运维·服务器
云qq1 小时前
x86操作系统23——进程相关系统调用
linux·c语言·汇编·ubuntu
小猪佩奇TONY1 小时前
Linux 内核学习(16) --- linux x86-64 虚拟地址空间和区域
linux·运维·学习