新闻详情

新闻详情

首页 / 资讯中心 / 详情

在ARM Linux上运行x86-64 Windows应用:FEX-Emu、Wine与DXMT组合方案详解

发布时间:2026/10/1 6:38:39来源:尧图网络
在ARM Linux上运行x86-64 Windows应用:FEX-Emu、Wine与DXMT组合方案详解
1. 项目缘起为什么要在 Linux 上折腾 Windows 应用兼容层第一次接触 Madeira 这个项目是在给一台老旧的 ThinkPad 装完某个国产 Linux 发行版之后。当时的需求很朴素这台机器性能一般跑虚拟机太吃资源但又必须用几个只有 Windows 版本的行业软件。翻了一圈社区方案FEX-Emu、Wine、DXMT 这几个名字反复出现而 Madeira 恰好是把这几块拼图整合到一起的那类项目——它不是一个从零造轮子的兼容层而更像是一套“让 x86-64 Windows 应用在 ARM Linux 上跑起来”的工程化组合方案。先把话说清楚Madeira 这类项目的核心价值在于解决架构翻译和系统调用翻译这两层问题。x86-64 的指令集和 ARM64 完全不是一回事Windows 的 PE 可执行格式和 Linux 的 ELF 也不是一回事Windows 的 Win32 API 和 Linux 的 POSIX 接口更是两套体系。FEX-Emu 负责第一层把 x86-64 指令动态翻译成 ARM64 指令Wine 负责第二层把 Win32 API 调用翻译成 POSIX 调用DXMT 则专门处理 Direct3D 到 Metal 的转换让图形应用不至于卡在渲染这一步。Madeira 做的事情是把这三者串成一条可用的链路并且处理好它们之间的边界问题。这套方案适合谁我的判断是三类人一是手里有 ARM 设备比如各类开发板、ARM 笔记本、部分国产平台但需要跑 Windows 软件的人二是对系统兼容层原理感兴趣、想动手研究指令翻译和 API 转换的开发者三是需要在 Linux 上做 Windows 应用测试、又不想开虚拟机的测试人员。如果你只是想安安静静用个软件那可能现成的商业方案更省心但如果你想搞清楚“为什么能跑起来”以及“跑不起来时该从哪查”那这套东西值得花时间。需要提前说明的是Madeira 本身并不是一个官方命名的成熟产品社区里叫这个名字的项目有过好几个版本有的偏实验性质有的已经能日常使用。我下面讲的内容是基于“FEX-Emu Wine DXMT 组合方案”这个技术路线来展开的具体到你手上的版本细节可能有出入但核心思路是通的。2. 整体架构拆解三层翻译是怎么串起来的2.1 指令层FEX-Emu 到底在翻译什么很多人第一次听说 FEX-Emu会以为它是个模拟器其实更准确的说法是动态二进制翻译器。模拟器是逐条解释执行性能损耗大动态翻译是把 x86-64 的指令块翻译成 ARM64 指令块翻译一次缓存起来下次直接跑缓存。这个区别很关键直接决定了性能上限。FEX-Emu 的工作流程大致是这样程序开始执行时它拦截 x86-64 的代码入口把一段基本块basic block翻译成等价的 ARM64 指令存进翻译缓存然后跳过去执行。执行到基本块末尾时再回到 FEX 的控制流里找下一个基本块。如果下一个块已经翻译过直接跳缓存没有就再翻译。这个过程对上层应用是透明的应用完全感知不到自己在被翻译。这里有个容易踩的坑自修改代码。有些程序会在运行时改写自己的指令比如某些加壳软件、JIT 编译器FEX 翻译过的缓存就失效了。FEX 的处理方式是检测到代码页被写入时把对应的翻译缓存标记为失效重新翻译。这个机制会带来性能抖动所以如果你跑的程序有大量自修改行为帧率或者响应速度会明显不稳。实测下来普通办公软件基本无感但某些老游戏和加密软件会比较明显。另一个关键点是寄存器映射。x86-64 有 16 个通用寄存器ARM64 有 31 个数量上 ARM64 更宽裕但标志位寄存器的语义不完全一样。FEX 需要在翻译时把 x86 的 EFLAGS 拆解成 ARM64 的条件标志或者用软件方式模拟。这部分是性能热点也是 FEX 团队优化最多的地方。你在配置时如果看到--flags之类的选项多半就是在调这块的行为。2.2 API 层Wine 不是模拟器是翻译器Wine 的全称是“Wine Is Not an Emulator”这句话不是玩梗是认真的。Wine 不翻译指令它翻译的是API 调用。Windows 程序调用CreateFileWWine 把这个调用翻译成 Linux 的open程序调用MessageBoxWine 用 X11 或者 Wayland 画一个对话框出来。所以 Wine 的性能损耗主要在 API 转换和图形栈上不在指令执行上。这就解释了一个常见现象同一个程序在 x86 Linux 上用 Wine 跑和用 FEX Wine 在 ARM Linux 上跑性能差距主要来自指令翻译那一层。如果程序是计算密集型的FEX 的开销会很明显如果是 IO 密集型或者图形密集型的Wine 这边的开销占比更大。Wine 的配置核心是WINEPREFIX。你可以把它理解成一个“虚拟的 Windows 目录”里面有自己的注册表、自己的 C 盘、自己的 DLL。每个 prefix 是独立的互不干扰。这个设计的好处是你可以给不同的程序建不同的 prefix装不同的运行库避免冲突。坏处是占磁盘而且新手容易搞混“我到底在哪个 prefix 里操作”。提示新建 prefix 时一定要指定架构。ARM 上跑 x86-64 程序prefix 要建 64 位的如果程序是 32 位的还得额外处理 wow64 层。建错了架构后面装什么都跑不起来。2.3 图形层DXMT 为什么是 ARM Mac 场景的关键DXMT 这个名字是 DirectX Metal 的组合。它的作用是把 Windows 程序的 Direct3D 调用翻译成 Apple Metal 调用。为什么需要它因为在 ARM Mac 上图形栈的底层是 MetalOpenGL 是转译层Vulkan 要通过 MoltenVK 转Direct3D 更是没有原生支持。DXMT 直接做 D3D 到 Metal 的映射少了一层转换效率更高。但 DXMT 的适用范围有边界。它主要覆盖 Direct3D 11 及以下D3D12 的支持要看版本。而且它依赖 Metal 的特性集老一些的 GPU 可能缺特性。如果你跑的程序用的是 OpenGL 或者 Vulkan那 DXMT 帮不上忙得走 WineD3D 或者 MoltenVK 那条路。在 Madeira 这套组合里DXMT 的位置是“图形加速的可选件”。不是所有程序都需要它但需要它的程序没有它就很痛苦。判断方法很简单如果程序启动后黑屏、花屏、或者帧率个位数而日志里出现 d3d 相关的报错那大概率就是图形层没走通。3. 环境准备从零搭建一套可用的运行环境3.1 系统与依赖的选型逻辑搭建这套环境第一步是选系统。我的建议是优先选滚动更新的发行版比如 Arch 系或者 Fedora 较新版本。原因很实际FEX-Emu 和 Wine 都在快速迭代老发行版的软件源里版本太旧很多新特性用不上遇到 bug 也没法通过升级解决。我自己在 Debian stable 上折腾过一轮最后卡在 Wine 版本太老、DXMT 编译不过换到滚动版之后顺畅很多。依赖方面核心是这几类编译工具链gcc、cmake、ninja、图形库mesa、vulkan-loader、libdrm、音频库pipewire 或 pulseaudio 的开发包、以及 Python 运行时Wine 的构建脚本要用。这些在各大发行版的包管理器里都有但包名不一样下面给个对照。依赖类别Debian/Ubuntu 包名Fedora 包名Arch 包名编译工具build-essential cmake ninja-buildgcc cmake ninja-buildbase-devel cmake ninja图形库libgl-dev libvulkan-devmesa-libGL-devel vulkan-loader-develmesa vulkan-icd-loader音频库libpipewire-0.3-devpipewire-develpipewirePythonpython3 python3-pippython3 python3-pippython python-pip装完依赖之后建议先跑一遍vulkaninfo和glxinfo确认图形栈是通的。这两个命令的输出里如果有你的 GPU 名字和可用的驱动说明底层没问题。如果这里就报错那后面 Wine 和 DXMT 再怎么配都是白搭。3.2 FEX-Emu 的获取与配置要点FEX-Emu 的获取方式有两种用发行版打包好的或者自己编译。我建议先用打包版跑通了再考虑自己编译。打包版的好处是依赖都处理好了坏处是版本可能不是最新。自己编译的好处是能拿到最新特性坏处是编译过程可能踩坑尤其是 LLVM 版本不匹配的时候。配置 FEX 的核心是几个环境变量。FEX_ROOTFS指向一个根文件系统FEX 会在里面找 x86-64 的动态链接库FEX_APP_CONFIG可以指定每个应用的配置FEX_LOG_LEVEL控制日志详细程度排查问题时调到 info 或 debug。这几个变量建议写进 shell 的启动脚本里省得每次手动设。注意FEX 的根文件系统需要包含 x86-64 版本的 glibc 和基础库。有些教程让你直接指向宿主系统的 /这在纯 ARM 系统上是不行的因为宿主没有 x86-64 的库。正确做法是准备一个 x86-64 的 rootfs可以用容器镜像解出来也可以用 debootstrap 之类的工具生成。实测下来FEX 的配置里最容易出问题的是rootfs 的路径权限。如果 FEX 进程没有权限读 rootfs 里的库程序会在启动阶段就挂掉日志里会出现 “cannot open shared object” 之类的报错。排查时先确认权限再确认路径拼写最后确认库的架构对不对。3.3 Wine 与 DXMT 的安装顺序Wine 和 DXMT 的安装顺序有讲究。正确顺序是先装 Wine建好 prefix再装 DXMT 到 prefix 里。反过来先装 DXMT 的话Wine 可能不认识那些 DLL或者版本对不上。Wine 的安装如果发行版有打包版就直接用。没有的话可以用 Wine 官方的构建脚本或者用社区维护的构建。ARM 平台上Wine 需要开启 wow64 支持才能跑 32 位程序编译时要加--enable-archsi386,x86_64之类的参数。具体参数看你的 Wine 版本新版和老版的选项名不一样。DXMT 的安装本质上是把编译好的 DLL 复制到 prefix 的drive_c/windows/system32和syswow64目录里然后改注册表让 Wine 优先加载它们。DXMT 的仓库里一般有安装脚本照着跑就行。但要注意DXMT 的 DLL 要和你 Wine 的架构匹配64 位 Wine 配 64 位 DLL别搞混。装完之后用winecfg打开配置界面在 “Libraries” 标签页里确认 d3d11、dxgi 这些库指向的是 DXMT 的版本而不是 Wine 自带的。这一步是很多人忽略的结果就是 DXMT 装了但没生效程序还是走软件渲染。4. 实操全流程从建 prefix 到跑起第一个程序4.1 建立干净的 Wine prefix第一步是建 prefix。命令很简单export WINEPREFIX$HOME/.wine-madeira export WINEARCHwin64 wineboot -u这三行的含义第一行指定 prefix 路径第二行指定架构为 64 位第三行初始化 prefix。wineboot -u会创建目录结构、注册表、以及基础的 DLL。执行完之后$WINEPREFIX目录下会出现drive_c、dosdevices等目录。这里有个细节WINEARCH 只在第一次建 prefix 时有效。如果 prefix 已经存在再设 WINEARCH 是没用的。所以如果你建错了架构只能删掉重来。删之前记得备份里面装的东西不然白装。建完 prefix 之后建议先跑一个最简单的程序验证环境比如wine notepad。如果记事本能弹出来说明 Wine 基础环境是通的。如果弹不出来看终端输出一般是缺库或者图形栈的问题。4.2 安装运行库与字体Windows 程序依赖一堆运行库最常见的是 VC 运行库和 .NET。Wine 自带了一部分但不全。社区常用的方案是用winetricks装。winetricks 是个脚本工具封装了常见的运行库安装流程。winetricks -q vcrun2019 corefonts这条命令装 VC 2019 运行库和核心字体。-q是静默模式不弹交互界面。装字体很重要因为 Wine 默认的字体渲染经常出问题中文程序尤其明显界面上的字要么是方块要么是乱码。corefonts 装的是微软的核心字体能解决大部分英文界面的显示问题中文界面还需要额外装中文字体可以用winetricks cjkfonts或者手动把字体文件复制到 prefix 的drive_c/windows/Fonts目录。提示winetricks 装运行库时有些会从网上下载安装包。如果你的网络环境访问那些地址不稳定可以提前把安装包下好放到 winetricks 的缓存目录里它会优先用缓存。4.3 配置 DXMT 并验证图形加速DXMT 装好之后需要验证它是否真的在工作。最直接的方法是跑一个 D3D 程序然后看日志。DXMT 会在日志里输出它拦截到的 D3D 调用和 Metal 的映射情况。如果日志里全是 DXMT 的输出说明它在工作如果日志里是 WineD3D 的输出说明 DXMT 没生效。另一个验证方法是看帧率。同一个程序开 DXMT 和不开 DXMT帧率差距通常很明显。如果差距不大要么是程序本身不吃图形要么是 DXMT 没生效。配置 DXMT 时有几个环境变量可以调DXMT_LOG_LEVEL控制日志DXMT_FRAME_RATE可以限制帧率省电用DXMT_SHADER_CACHE指定着色器缓存路径。着色器缓存建议开因为 D3D 程序的着色器编译很耗时缓存下来能大幅减少二次启动的等待。4.4 跑起第一个 x86-64 Windows 程序前面都是准备现在跑一个真实的 x86-64 Windows 程序。假设你有一个test.exe放在$HOME/test.exe执行export FEX_ROOTFS/path/to/x86_64/rootfs export WINEPREFIX$HOME/.wine-madeira FEXBash -c wine $HOME/test.exeFEXBash是 FEX 提供的一个包装脚本它会在 FEX 的翻译环境里启动 bash然后 bash 里执行的命令就是被翻译的。这样 wine 本身也是 x86-64 版本整个链路都在翻译环境里跑。如果程序启动了但界面有问题先看终端输出。常见的报错分几类缺 DLL、图形初始化失败、字体缺失。缺 DLL 就用 winetricks 补图形失败就查 DXMT 配置字体缺失就装字体。这个排查顺序基本能覆盖八成问题。5. 常见问题与排查技巧实录5.1 程序启动即崩溃怎么查启动即崩溃是最常见也最难查的问题因为信息太少。我的排查顺序是先看终端输出再看 Wine 的日志最后用 strace 跟系统调用。终端输出里如果有 “Unhandled exception” 或者 “page fault”说明程序在翻译后的代码里崩了。这时候要确认 FEX 的 rootfs 是不是完整尤其是 glibc 的版本。x86-64 程序依赖的 glibc 版本如果比 rootfs 里的高就会在启动阶段崩。Wine 的日志可以用WINEDEBUGall打开但输出量巨大建议按通道过滤比如WINEDEBUGd3d11,dxgi只看图形相关的。日志里如果有 “err:” 开头的行优先看那些。strace 是最后的手段用来确认程序到底卡在哪个系统调用上。用法是strace -f -o trace.log wine test.exe然后看 trace.log 的末尾。如果卡在某个open或者connect上说明是文件或网络的问题。5.2 界面乱码与字体问题的根治方法界面乱码基本是字体问题。Wine 的字体处理逻辑是程序请求某个字体Wine 在 prefix 的字体目录和系统字体目录里找找不到就用替代字体。替代字体的字符集如果不全就显示方块或乱码。根治方法是把常用的中文字体装进 prefix。具体操作把simsun.ttc、msyh.ttf之类的字体文件复制到$WINEPREFIX/drive_c/windows/Fonts然后在注册表里把默认字体映射改掉。注册表路径是HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes把MS Shell Dlg和MS Shell Dlg 2映射到你装的中文字体。改完注册表要重启 Wine 才生效。如果还是乱码检查字体文件的权限Wine 进程要能读到。另外有些程序会自己带字体这种情况下乱码可能是程序内部的编码问题不是 Wine 的锅。5.3 图形程序黑屏或花屏的排查路径黑屏和花屏九成是图形层的问题。排查路径是先确认 DXMT 是否加载再确认 Metal 是否可用最后确认着色器是否编译成功。确认 DXMT 加载看WINEDEBUGloaddll的输出里面会列出加载的 DLL 和路径。如果 d3d11.dll 的路径是 DXMT 的目录说明加载了如果是 Wine 自带的目录说明没加载要检查注册表里的 DLL 覆盖设置。确认 Metal 可用跑一个原生的 Metal 程序或者用system_profiler SPDisplaysDataType看 GPU 信息。如果 Metal 本身有问题DXMT 肯定也跑不起来。着色器编译失败日志里会有 “shader compilation failed” 之类的报错。这种情况一般是 DXMT 的版本和程序用的 D3D 特性不匹配。解决办法是升级 DXMT或者在 DXMT 的配置里关掉某些高级特性。5.4 性能调优的几个实用开关性能调优的核心是减少翻译开销和图形开销。FEX 这边可以开翻译缓存持久化把翻译过的块存到磁盘下次启动直接加载省去重新翻译的时间。开关一般在 FEX 的配置文件里具体名字看版本。Wine 这边可以关掉不必要的调试输出WINEDEBUG-all能省一点开销。另外Wine 的csmt选项命令流多线程对图形程序有帮助可以在注册表里开。DXMT 这边着色器缓存一定要开DXMT_SHADER_CACHE指向一个可写目录。另外如果程序不需要高帧率用DXMT_FRAME_RATE限制一下能省不少电。调优项作用配置方式FEX 翻译缓存减少重复翻译FEX 配置文件WINEDEBUG-all减少日志开销环境变量csmt图形命令多线程注册表DXMT 着色器缓存减少着色器编译环境变量DXMT 帧率限制省电环境变量6. 几个容易忽略的细节与个人体会第一个细节是路径里的空格和中文。Wine 对路径的处理有时候会出问题尤其是路径里有空格或者非 ASCII 字符时。我的习惯是把 prefix 和程序都放在纯英文、无空格的路径下省得排查这类问题。第二个细节是时区和编码。Wine 默认的时区可能和宿主不一致导致程序里的时间显示不对。可以在 prefix 里设TZ环境变量或者在 winecfg 里改。编码问题主要体现在老程序上GBK 编码的程序在 UTF-8 环境下可能乱码需要设LANG或者用wineconsole调整。第三个细节是进程管理。Wine 跑的程序有时候会在后台留残留进程尤其是图形程序。这些残留进程会占着 prefix 不放导致下次启动失败。遇到这种情况用wineserver -k杀掉所有 Wine 进程再重新启动。我个人在实际操作中的体会是这套方案的上限很高但下限也低。配置对了日常办公和轻度游戏都能跑配置错了连记事本都弹不出来。关键是要有耐心遇到问题按层排查先确认 FEX 层通不通再确认 Wine 层通不通最后确认图形层通不通。每一层都有对应的验证方法不要跳步。最后分享一个小技巧给每个程序建独立的 prefix。虽然占磁盘但能避免运行库冲突。尤其是那些对运行库版本敏感的程序独立 prefix 能省掉大量排查时间。磁盘现在便宜这点空间换来的稳定性很值。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

支付行业中的T0、T1、TS、D1是什么 2026/10/1 10:23:18

支付行业中的T0、T1、TS、D1是什么

1、定义这些字母是支付行业描述结算到账周期的通用缩写,核心先记住三个字母:T Trade(交易日):仅指工作日,周末和法定节假日不算D Day(自然日):一年 365 天都算&#xf…

阅读更多 →
nanoGPT OpenWebText 数据管线拆解:801 万篇网页如何变成 90 亿个 token 2026/10/1 10:23:18

nanoGPT OpenWebText 数据管线拆解:801 万篇网页如何变成 90 亿个 token

nanoGPT OpenWebText 数据管线拆解:801 万篇网页如何变成 90 亿个 token 【免费下载链接】nanoGPT The simplest, fastest repository for training/finetuning medium-sized GPTs. 项目地址: https://gitcode.com/GitHub_Trending/na/nanoGPT 8,013,769 篇网…

阅读更多 →
Radioss的1D单元应用 2026/10/1 10:23:18

Radioss的1D单元应用

这篇教程里&#xff0c;你会学到哪些1D单元&#xff1f;<汽车中1D单元运用示例>TRUSS TYPE2杆单元两个节点构成的杆单元具有一个自由度&#xff0c;只能描述压缩/拉伸性质。与线弹性材料LAW1和弹塑性材料LAW2兼容。需要定义横截面积和初始长度&#xff1a;BEAM TYPE3梁单…

阅读更多 →
Agent 的困境与运筹学解法:从“会聊天”到“会决策” 2026/10/1 10:23:18

Agent 的困境与运筹学解法:从“会聊天”到“会决策”

1. 引言 2025 年以来&#xff0c;Agent&#xff08;智能体&#xff09;成为大模型落地最热的方向。从自动写代码、操作浏览器&#xff0c;到多 Agent 协作完成复杂任务&#xff0c;Agent 展现出惊人的潜力。然而&#xff0c;随着应用深入&#xff0c;一系列问题也开始集中暴露&…

阅读更多 →
OpenBMC:传感器不显示问题排查 2026/10/1 10:23:17

OpenBMC:传感器不显示问题排查

OpenBMC&#xff1a;传感器不显示问题排查 1. 先定位数据消失的位置 传感器从硬件到页面通常经过&#xff1a; 硬件 → 内核驱动 → hwmon → Sensor 服务 → D-Bus → Redfish → WebUI“页面没有传感器”可能发生在其中任意一层。首先判断它是完全没有创建&#xff0c;还是已…

阅读更多 →
保险代理人 GEO 实操:让 AI 推荐你作为本地家庭保障顾问 2026/10/1 10:23:11

保险代理人 GEO 实操:让 AI 推荐你作为本地家庭保障顾问

真实案例&#xff1a;一位在二线城市从业 6 年的保险代理人&#xff0c;过去主要靠熟人转介绍获客&#xff0c;每月新增咨询量长期在个位数徘徊。她按照 GEO 方法&#xff0c;先统一了全网执业信息&#xff0c;再围绕「重疾险保额怎么定」「网上买保险理赔麻烦吗」等高频问题&a…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉