System32 为什么放 64 位文件?SysWOW64 又是什么

Win11 里 System32 放 64 位文件,SysWOW64 放 32 位文件,名字看着是反的。本文按微软文档讲清原因、WOW64 重定向机制,以及 Arm 电脑上的新变化。

打开 C 盘的 Windows 文件夹,您会发现一件怪事:放 64 位文件的叫 System32,放 32 位文件的反而叫 SysWOW64。先说结论:这是微软为了兼容几十年的老软件留下来的”历史包袱”,System32 里放的是”跟当前系统位数一致的文件”,名字里的 32 早就不代表位数了。

微软早就不出 32 位的 Windows 11,但系统仍然要运行大量老旧的 32 位软件。微软的办法是两个系统文件夹加一个”文件系统重定向器”(WOW64):64 位文件放 System32,32 位副本放 SysWOW64,32 位程序访问 System32 时,系统在背后悄悄把它转到 SysWOW64。小编在 Windows 11 26H2 上看了一下,两个文件夹里都有 kernel32.dll,但文件大小不一样,因为一个是给 64 位程序用的,一个是给 32 位程序用的。

Windows 11 26H2 中 System32 与 SysWOW64 都有 kernel32.dll,但 64 位和 32 位副本大小不同

要是微软能像苹果那样宣布不再支持 32 位软件,Windows 的包袱可能会轻不少,不过这也只是小编的一点感慨。

System32 为什么放 64 位文件,SysWOW64 放 32 位文件

咱们先回头看历史。16 位 Windows 时代,系统文件放在 C:\Windows\System;32 位 Windows 出现后,微软新增了 C:\Windows\System32 放 32 位文件,名字里的”32″就是这么来的。

等 64 位 Windows 来了,很多程序把 System32 路径直接写死,而不是通过 GetSystemDirectory 函数去问系统。微软老员工 Raymond Chen 在 Windows Confidential 专栏 里解释过:这些程序重新编译成 64 位后,仍然去 System32 找文件,而且期待找到的是 64 位文件。批处理脚本也有类似问题,比如脚本里写 System32\reg.exe,如果这个文件夹里是 32 位工具,改的就会是 32 位的注册表视图。

所以 Windows 团队定下规矩:System32 放跟系统位数匹配的文件。微软的 文件系统重定向器文档 写得很明白:”%windir%\System32 目录在 64 位 Windows 上保留给 64 位应用程序。”另外,大多数 DLL 在做 64 位版本时没有改文件名,kernel32.dll 这种遵循 MS-DOS 命名规则的名字,在两个文件夹里都叫 kernel32.dll,所以 32 位副本只好另找一个文件夹。

Chen 的原话是:”这个 32 只是名字的一部分,没有什么含义。”他把它比作 KFC、HSBC 这类如今只用缩写的品牌,还说在更理想的世界里,这个文件夹应该叫 SysExec,因为它放的是与正在运行的程序相匹配的文件。

WOW64 是”Windows 32-bit on Windows 64-bit”的缩写,也就是微软给 32 位程序准备的兼容层。所以 SysWOW64 里的”64″指的是系统,里面的文件其实是 32 位的。有点讽刺的是,名字里带 64 的这个文件夹,恰恰是 64 位程序用不到的。

Windows 11 怎么悄悄把 32 位程序转到 SysWOW64

根据微软的 运行 32 位应用程序指南,32 位进程不能加载 64 位 DLL,反过来也一样。要是没有重定向,32 位程序从 System32 加载 kernel32.dll,拿到的是一个它根本用不了的文件。所以只要 32 位程序在 x64 Windows 上访问这些路径,WOW64 就会在后台替它换路径。

32 位程序请求的路径64 位 Windows 实际指向
C:\Windows\System32C:\Windows\SysWOW64
C:\Windows\lastgood\system32C:\Windows\lastgood\SysWOW64
C:\Windows\regedit.exeC:\Windows\SysWOW64\regedit.exe

程序本身完全不知道发生了什么。小编从 C:\Windows\SysWOW64\cmd.exe 打开 32 位命令提示符,输入 echo %PROCESSOR_ARCHITECTURE% 返回 x86,而普通命令提示符返回 AMD64。接着在两个窗口里分别运行 dir C:\Windows\System32\kernel32.dll,同一个路径出现了两个不同的文件大小。

32 位命令提示符显示 x86,访问 System32 时看到的是 SysWOW64 的 kernel32.dll
任务管理器显示哪个命令提示符是 32 位进程

连当年微软 Visual Studio 团队的 Matt Pietrek 也被它绕晕过。他在 2006 年的 MSDN 杂志文章 里写道,他曾在 32 位命令提示符里分别列出两个文件夹里的 kernel32.dll,结果两边一模一样,纳闷了好一阵。

除了文件,WOW64 还通过 注册表重定向器 给 32 位程序一份独立的注册表视图,位置在 HKEY_LOCAL_MACHINE\Software\Wow6432Node,同时把它们的 %ProgramFiles% 变量指向 Program Files (x86)。

Windows 11 中 32 位应用在 WOW6432Node 下拥有独立的注册表视图

有个细节比较怪:如果打开被重定向的文件时弹出了 UAC(用户账户控制)提示,微软说这时重定向不会发生,系统会启动 64 位版本,所以开发者应该直接使用 SysWOW64 路径,或者以管理员身份运行那个 32 位程序。

还有一个叫 Sysnative 的”虚拟文件夹”,您在 C:\Windows 里是找不到它的,64 位程序也不能用它。小编在文件资源管理器(64 位程序)的地址栏输入 C:\Windows\Sysnative,Windows 提示找不到;但在 32 位命令提示符里运行 dir C:\Windows\Sysnative\cmd.exe 却一切正常。

Sysnative 只对 32 位程序有效,64 位文件资源管理器找不到它

开发者也可以用 Wow64DisableWow64FsRedirection 函数关掉重定向,但它会影响该线程里所有的文件操作。微软 文档 警告说:”禁用文件系统重定向会导致 DLL 加载失败。”

顺带一提,TechNet 编辑嫌 Chen 专栏里的 Sysnative 说明太长给删了,他后来在自己的 2010 年博客 里补发,称它是”本地问题的本地解决办法”。2008 年 他还劝过一位开发者别跟模拟层对着干,让 32 位安装程序直接去启动 64 位安装程序。小编也同意,大多数麻烦都出在 32 位程序想”冒充”64 位程序的时候。

6 个 System32 子文件夹不会被重定向

微软列出了 6 个 System32 子文件夹,32 位程序访问它们时不会被重定向:

  • C:\Windows\System32\catroot
  • C:\Windows\System32\catroot2
  • C:\Windows\System32\driverstore
  • C:\Windows\System32\drivers\etc
  • C:\Windows\System32\logfiles
  • C:\Windows\System32\spool

这份名单并不是一直如此:driverstore 在 Windows Vista、XP、Server 2003 和 Server 2008 上是被重定向的。微软没有解释这些例外,小编猜测是因为这些文件夹放的是两种程序都要共用的数据,比如 drivers\etc 里的 hosts 文件,只需要一份。

Arm 电脑上的 SysArm32 正在消失

在骁龙 X 这类 Arm 笔记本上,32 位 x86 程序同样被转到 SysWOW64,而 32 位 Arm 程序以前被重定向到第三个文件夹 SysArm32。区别在于:Arm64 上的 WOW64 是用名为 xtajit.dll 的模拟器翻译 x86 代码,而 x64 处理器是原生运行 32 位代码,由 Wow64Cpu.dll 负责切换,详见微软的 实现细节文档。

微软的 Arm 开发者文档 现在写明:Arm 电脑不再支持 32 位 Arm 应用,sysarm32 文件夹里的系统二进制文件也会被移除。普通的 x86 应用(不管 32 位还是 64 位)依然通过 Prism 模拟运行,Prism 去年还加入了 AVX 和 AVX2 支持。

总的来说,微软当年本可以直接把 System32 改名,但那会让一大堆软件失灵,于是选择围着这个旧名字建了重定向器、别名和例外清单,就像为了老程序一直留着 Windows 95 的堆管理器那样。不过也不是所有东西都挺过了 64 位的过渡,三维弹球(3D Pinball)就是例子。小编个人倒是挺想要一个叫 SysExec 的文件夹,但名字让人困惑,总比安装程序崩溃强。

常见问题(FAQ)

System32 和 SysWOW64 可以随便删吗?

千万别删。两个文件夹里都是系统运行必需的文件,删了会导致系统或软件无法启动。

怎么知道一个程序是 32 位还是 64 位?

打开任务管理器的”详细信息”页,右键列标题添加”平台”列,32 位程序会显示”32 位”;旧版任务管理器里则会在进程名后面标注”(32 位)”。

为什么 32 位命令提示符里看到的 System32 和别处不一样?

因为 WOW64 重定向器把 32 位程序对 System32 的访问转到了 SysWOW64,所以同一个路径在 32 位和 64 位窗口里看到的是不同文件。

Sysnative 是什么?

它是仅对 32 位程序有效的虚拟路径,用来让 32 位程序访问真正的 64 位 System32,在资源管理器里是看不到的。

Arm 电脑能运行 32 位程序吗?

能运行 32 位和 64 位的 x86 程序(通过 Prism 模拟),但微软文档说 Arm 电脑已不再支持 32 位 Arm 应用。