25年后谜底揭晓:XP挑头像不是抓阄,看的是开机时长

25年后谜底揭晓:XP挑头像不是抓阄,看的是开机时长

Windows XP历史

数据源:HN + web research

全世界数亿人以为,Windows XP 第一次开机分配的初始头像是纯随机的。2026年9月9日,微软老员工 Raymond Chen 贴出一段代码,揭开了这段藏了 25 年的系统逻辑。那个看似随缘的开机头像并非抓阄,而是算出确切结果的。

一条推特引发的代码考古

2025 年 12 月 11 日,名为 Xeno 的用户在推特上发问。他想弄明白 XP 系统创建账户时到底用了什么算法来分配头像。这是一个困扰了社区二十多年的老问题。早在 2004 年 4 月,Raymond Chen 就曾在文章里提过 XP 头像是随机挑选的。但这根本无法满足硬核开发者的好奇心。他们不要结论,他们要看具体的代码和算法推导。

Raymond Chen 最终在他的博客 The Old New Thing 上贴出了具体的代码逻辑。这篇技术文章在 Hacker News 上迅速拿下了 333 分和 162 条评论。大家发现,当年发到自己手里的吉他、花或者国际象棋,根本不是从暗箱里随便摸出来的。这背后有一套严密计算的数学流程。

初始种子锁定开机毫秒数

Windows XP 的这些初始头像文件存放在一个非常深的文件层级里。具体路径是 %ALLUSERSPROFILE%\Application Data\Microsoft\User Account Pictures\Default Pictures。系统在建立新账户时,需要从这个文件夹里挑出一张图片。

这里的核心调用是 Windows 内部自带的 RtlRandomEx 伪随机数生成器。任何伪随机算法都需要一个初始种子。微软工程师没有选用复杂的硬件熵源。他们直接拿了 GetTickCount() 的返回值作为种子。这个函数返回的是系统从启动那一刻到当前经过的精确毫秒数。

**伪随机算法有明确的输入条件。只要有人精确记录下那台电脑开机花了多少毫秒,就能算出会拿到什么图。**不可预测仅仅是对用户而言的视觉感受,在代码层面这是一个确定的过程。

蓄水池抽样把遍历压到单次

面对未知数量的图片目录,常规的做法是两步走。也就是先遍历一遍目录数出总数,再用总数生成一个随机下标,最后再遍历一遍去拿特定位置的文件。这就是典型的两次遍历法。

微软工程师没有这么做。他们用了一次遍历算法。系统在扫描目录时只维护一个计数器 count 和一个当前赢家 winner。每读到一项,就把 count 加一。然后系统以 1/count 的概率决定要不要把 winner 换成当前读到的图片。读完整个目录后,最后拿在手里的 winner 就是最终结果。

selectRandomFromIterator 一次遍历算法代码 图:selectRandomFromIterator 一次遍历算法代码。来源:The Old New Thing

这正是蓄水池抽样在 k=1 时的经典特例。当目录里有 n 个文件时,最后一个文件被选中的概率是严格的 1/n。如果它没有被选中,问题就递归地变成了在前 n-1 个文件里做同样挑选。无论目录里有多少文件,每一个文件最终留在手里的概率都是均等的。

数学理论向系统读写妥协

为什么不用简单粗暴的两次遍历,非要用蓄水池抽样?答案藏在操作系统的底层瓶颈里。在建立账户这个节点上,文件系统调用的开销远大于纯 CPU 的计算开销。早期的机械硬盘在处理大量小文件遍历时性能很差。

单次遍历大幅降低了文件系统的调用耗时。即便目录里的文件在算图间隙变动,这套一次遍历流程也不会报错。

两次遍历法要求文件总数在两次扫描之间保持绝对稳定。如果在第一次数数和第二次取值的间隙里,有其他程序动了那个图片目录,系统就会因为越界而崩溃。一次遍历机制完美规避了这个时序窗口里的并发风险。

扫描到 100 张图片立刻停工

蓄水池抽样在数学上是完美的。随着计数器不断增大,手里那张牌被换掉的概率会等比缩小。但操作系统代码永远不会无限次地抽签下去。在这段核心逻辑里,工程师硬编码了一个简单暴力的保护策略。

当采样图片达到 100 张时,算法会直接强制跳出循环,返回当前手里的图片。

Windows XP 默认 Luna 界面 图:Windows XP 默认 Luna 界面。来源:Wikipedia

**一线工程师从来不迷信完美的纯数学推导。设下 100 张的物理边界,是为了防止有人塞进百万级文件把开机流程拖死。**数学模型需要保证对无限总体的均匀分布,而工业代码的最高责任是保证系统永远不挂掉。

随缘假象下藏着精密算计

回到推特上的那个初始疑惑。无数人在 2001 年到 2014 年间经历了第一次打开 XP 的激动时刻。他们看着屏幕上的足球或者青蛙,以为那是系统随缘派发的惊喜。大众无法感知开机过程中的微小耗时差异。几毫秒的波动,在他们眼里就成了真正的随机。

Raymond Chen 的文章解答了一个尘封的疑惑。这也像是给当年的软件工程留下了一张快照。那时候的内存很小,硬盘很慢。每一行代码都需要精打细算,每一个边缘场景都需要防御性编程。

25 年前那张看似随缘派发的系统图片,根本不是随便抽取的签筒。它实际上是用明确的文件边界和抽样逻辑,给两代用户做了一次精密的算计。

参考链接:

  • The Old New Thing
  • HN
  • Wikipedia