Phase1Initialization 函数分析

Phase1Initialization 函数分析

1. 概述

Phase1Initialization 是内核 Phase 1 初始化的入口线程函数,由 PsInitSystem 在 Phase 0 末尾创建。它运行在一个真正的系统线程上下文 中(而非空闲线程),负责初始化完整的 I/O 系统、加载启动驱动、创建系统进程、最终启动会话管理器 (SMSS)。这个函数永不返回。

文件位置: ntoskrnl/ex/init.c#L2056-L2065(file:///d:/reactos/ntoskrnl/ex/init.c#L2056)

c 复制代码
VOID
NTAPI
Phase1Initialization(IN PVOID Context)
{
    /* Do the .INIT part of Phase 1 which we can free later */
    Phase1InitializationDiscard(Context);

    /* Jump into zero page thread */
    MmZeroPageThread();
}

函数只有两行,但实际工作委托给 Phase1InitializationDiscard(约 700 行),完成后进入零页线程。


2. 函数结构

复制代码
Phase1Initialization(Context)
  └─ Phase1InitializationDiscard(Context)  [约 700 行, CODE_SEG("INIT")]
      └─ 返回后:
           └─ MmZeroPageThread()            [永不返回]

Phase1InitializationDiscard 被标记为 CODE_SEG("INIT"),初始化完成后可被丢弃/回收。


3. Phase1InitializationDiscard 执行流程

流程图

复制代码
Phase1InitializationDiscard(LoaderBlock)
│
├─ 0. 分配 INIT_BUFFER + 设置 Phase 标志 + 提升线程优先级
│
├─ 1. HalInitSystem(1, LoaderBlock)     ← HAL Phase 1
│     (完整 HAL 初始化: 中断控制器、时钟、DMA 等)
│
├─ 2. 启动视频初始化
│     ├─ 解析 NOGUIBOOT / SOS 选项
│     ├─ InbvDriverInitialize() --- 初始化启动视频驱动
│     ├─ 显示启动 Logo (或释放显示所有权)
│     └─ 检测 WinPE 模式 (MININT)
│
├─ 3. 显示版本横幅
│     ├─ 从消息表中查找 WINDOWS_NT_BANNER
│     ├─ 构建版本字符串 (含 CSDVersion)
│     └─ InbvDisplayString() --- 在屏幕上打印
│
├─ 4. 电源初始化 Phase 0
│     └─ PoInitSystem(0)
│
├─ 5. 系统时间初始化
│     ├─ HalQueryRealTimeClock() --- 读取 CMOS/RTC
│     ├─ Y2K 年号修正 (YEAR= 选项)
│     ├─ 计算时区偏差 (ExpTimeZoneBias)
│     ├─ KeSetSystemTime() --- 设置系统时间
│     └─ 记录 KeBootTime
│
├─ 6. [SMP] 启动 AP 处理器
│     ├─ 解析 NUMPROC/BOOTPROC/MAXPROC 选项
│     ├─ KeStartAllProcessors() --- 唤醒所有 AP
│     └─ HalAllProcessorsStarted() --- 等待全部就绪
│
├─ 7. 显示处理器和内存信息
│     ├─ 打印 "N System Processor [M MiB Memory]"
│     └─ InbvUpdateProgressBar(5)
│
├─ ★ 8. 执行体子系统 Phase 1 初始化 ★
│     ├─ ObInitSystem()                --- 对象管理器 Phase 1
│     ├─ ExInitSystem()                --- 执行体初始化 (Worker 线程)
│     ├─ KeInitSystem()                --- 内核调度器 Phase 1
│     ├─ KdInitSystem(1, ...)          --- 调试器 Phase 1
│     ├─ SeInitSystem()                --- 安全引用监视器 Phase 1
│     │
│     ├─ InbvUpdateProgressBar(10)
│     │
│     ├─ ExpCreateSystemRootLink()     --- 创建 \??\SystemRoot 符号链接
│     ├─ MmInitSystem(1, ...)          --- 内存管理器 Phase 1
│     │                                 (区域映射、段、分页文件)
│     ├─ ExpInitNls()                  --- NLS 数据初始化
│     ├─ CcInitializeCacheManager()    --- 缓存管理器初始化
│     ├─ CmInitSystem1()               --- 配置管理器 Phase 1 (注册表)
│     ├─ CcPfInitializePrefetcher()    --- 预取器初始化
│     │
│     ├─ InbvUpdateProgressBar(15)
│     │
│     ├─ 时区刷新 + 启动时间校正
│     ├─ FsRtlInitSystem()             --- 文件系统运行时库
│     ├─ HalReportResourceUsage()      --- HAL 报告资源使用
│     ├─ KdDebuggerInitialize1()       --- KD 调试器初始化
│     ├─ PpInitSystem()                --- PnP 管理器 Phase 1
│     │
│     ├─ InbvUpdateProgressBar(20)
│     │
│     ├─ LpcInitSystem()               --- LPC (本地过程调用) 初始化
│     │
│     ├─ 安全模式检测 + BootLog 检测
│     │
│     ├─ InbvUpdateProgressBar(25)
│     │
│     ├─ XIPInit()                     --- XIP (就地执行) 初始化
│     └─ InbvSetProgressBarSubset(25, 75)
│
├─ ★ 9. IoInitSystem(LoaderBlock) ★     ← I/O 管理器 (关键!)
│     └─ 加载启动驱动、PnP 枚举、创建设备栈
│
├─ 10. (安全模式时) 注册安全模式配置
│      ├─ 写入 SafeBoot 注册表键
│      └─ 处理 AlternateShell
│
├─ 11. WinPE 模式注册
│      └─ 创建 HKLM\...\Control\MiniNT 键
│
├─ 12. MmArmInitSystem(2, ...) + VDM 初始化
│     └─ InbvUpdateProgressBar(80)
│
├─ 13. PoInitSystem(1)                ← 电源管理 Phase 1
│     └─ InbvUpdateProgressBar(90)
│
├─ 14. PsInitSystem(LoaderBlock)       ← 进程管理器 Phase 1
│     └─ (创建系统进程、初始化模块加载等)
│
├─ 15. ★ 释放 LoaderBlock ★
│     └─ MmFreeLoaderBlock(LoaderBlock)
│
├─ 16. SeRmInitPhase1()                ← 安全引用监视器 Phase 1
│     └─ InbvUpdateProgressBar(100)
│
├─ 17. FinalizeBootLogo()              ← 清除启动画面
│
├─ ★ 18. ExpLoadInitialProcess() ★    ← 启动 SMSS.EXE
│     ├─ 构造 SMSS 进程参数 (路径、环境变量)
│     ├─ RtlCreateUserProcess() --- 创建 smss.exe 进程
│     └─ ZwResumeThread() --- 恢复 SMSS 线程执行
│
├─ 19. ZwWaitForSingleObject(SMSS, 5s)← 等待 SMSS 初始化
│     ├─ STATUS_SUCCESS → SMSS 已终止 → BUGCHECK
│     └─ STATUS_TIMEOUT → SMSS 正常运行 → 继续
│
├─ 20. 清理
│     ├─ ZwClose 进程/线程句柄
│     ├─ 释放环境变量和参数内存
│     ├─ ExpInitializationPhase++
│     └─ ExFreePoolWithTag(InitBuffer)
│
└─ [返回 Phase1Initialization]
    └─ [进入 MmZeroPageThread 永不返回]

4. 函数执行详解

4.0 准备工作 (L1374-L1388)

c 复制代码
InitBuffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(INIT_BUFFER), TAG_INIT);
ExpInitializationPhase = 1;
KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
  • 分配 INIT_BUFFER(版本缓冲区、调试缓冲区、进程信息等的容器)
  • 将全局 Phase 标志设为 1
  • 将当前线程优先级提升到最高,确保初始化不被其他线程打断

4.1 HAL Phase 1 (L1391)

c 复制代码
if (!HalInitSystem(1, LoaderBlock)) KeBugCheck(HAL1_INITIALIZATION_FAILED);

HAL Phase 1 的完整初始化,与 Phase 0 的轻量初始化不同:

  • 初始化完整的中断控制器 (PIC/APIC/IOAPIC)
  • 时钟定时器校准和配置
  • DMA 控制器初始化
  • HAL 特定的资源报告

4.2 启动视频和显示 (L1393-L1428)

c 复制代码
NoGuiBoot = (CommandLine && strstr(CommandLine, "NOGUIBOOT"));
SosEnabled = (CommandLine && strstr(CommandLine, "SOS"));

InbvEnableBootDriver(!NoGuiBoot);
InbvDriverInitialize(LoaderBlock, IDB_MAX_RESOURCES);

if (!NoGuiBoot) { InbvEnableDisplayString(SosEnabled); DisplayBootBitmap(SosEnabled); }
else { InbvNotifyDisplayOwnershipLost(NULL); InbvEnableDisplayString(FALSE); }
  • InbvDriverInitialize() 从 LoaderBlock 中读取启动视频驱动(bootvid.dll/lfbbvid.dll),初始化显示模式
  • 非 NOGUIBOOT 模式:显示 ReactOS 启动 Logo
  • SOS 模式:在 Logo 上叠加显示模块加载信息
  • NOGUIBOOT 模式:释放显示所有权

WinPE (LiveCD) 检测 --- MININT 选项设置 InitIsWinPEMode = TRUE

4.3 启动横幅 (L1431-L1517)

  • 从内核的 PE 消息资源中查找 WINDOWS_NT_BANNER 消息条目
  • 构建版本字符串:KERNEL_VERSION_STR + NtBuildLab + 版本号 + CSDVersion
  • InbvDisplayString() 在屏幕上打印

4.4 系统时间初始化 (L1519-L1567)

c 复制代码
PoInitSystem(0);  // 电源 Phase 0

if (ExCmosClockIsSane && HalQueryRealTimeClock(&TimeFields))
{
    if (Y2KHackRequired) TimeFields.Year = (CSHORT)YearHack;
    RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
    // ... 时区计算 ...
    KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
    KeBootTime = UniversalBootTime;
}
  • 通过 HAL 读取 CMOS/RTC 时间
  • Y2K Hack : 如果启动参数包含 YEAR=XXXX,覆盖读取的年份(处理 BIOS Y2K Bug)
  • 根据时区偏差计算本地时间 → 设置系统时间
  • 记录 KeBootTime 供后续使用

4.5 AP 处理器启动 (L1569-L1603) 仅 SMP

c 复制代码
// 解析 NUMPROC/BOOTPROC/MAXPROC
KeStartAllProcessors();       // 唤醒 AP
if (!HalAllProcessorsStarted()) KeBugCheck(...);

在多处理器系统中,在此处唤醒所有应用处理器 (AP)KeStartAllProcessors 发送 IPI 中断,使所有 AP 从 KiSystemStartupAppCpuInit 自旋等待中释放,进入各自的 KiSystemStartupBootStack 初始化路径。

处理器限制选项

选项 含义
NUMPROC=N 最大逻辑处理器数(运行时可动态增加)
BOOTPROC=N 启动时最大处理器数
MAXPROC 报告系统支持的处理器上限

4.6 处理器和内存信息显示 (L1605-L1655)

复制代码
N System Processor [M MiB Memory]
  • 构建字符串并用 InbvDisplayString 显示
  • 单处理器显示单数,多处理器显示复数
  • 物理内存大小向上取整到 MiB

4.7 执行体子系统 Phase 1 (L1657-L1843)

这是最密集的初始化阶段,按顺序初始化所有内核子系统:

函数 失败时的 BugCheck 职责
ObInitSystem() OBJECT1_INITIALIZATION_FAILED 对象管理器: 完成对象类型注册
ExInitSystem() PHASE1_INITIALIZATION_FAILED 执行体: 创建工作线程 (Worker Threads)
KeInitSystem() PHASE1_INITIALIZATION_FAILED 调度器: 最终初始化
KdInitSystem(1, ...) PHASE1_INITIALIZATION_FAILED 调试器: 连接调试客户端
SeInitSystem() SECURITY1_INITIALIZATION_FAILED 安全引用监视器: 审计策略初始化
ExpCreateSystemRootLink() SYMBOLIC_INITIALIZATION_FAILED 创建 \??\SystemRoot\Device\...
MmInitSystem(1, ...) MEMORY1_INITIALIZATION_FAILED 内存管理器: 区域映射、段、分页文件
ExpInitNls() --- 加载 NLS 数据到系统
CcInitializeCacheManager() CACHE_INITIALIZATION_FAILED 缓存管理器: 初始化文件缓存
CmInitSystem1() CONFIG_INITIALIZATION_FAILED 配置管理器: 完成注册表初始化
FsRtlInitSystem() FILE_INITIALIZATION_FAILED 文件系统运行时库
PpInitSystem() PP1_INITIALIZATION_FAILED PnP 管理器 Phase 1
LpcInitSystem() LPC_INITIALIZATION_FAILED LPC (本地过程调用)
XIPInit() --- XIP (eXecute-In-Place) 支持

4.8 ★ IoInitSystem --- I/O 管理器 (L1849)

c 复制代码
if (!IoInitSystem(LoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);

这是 Phase 1 中最关键的步骤。IoInitSystem 的职责:

复制代码
IoInitSystem(LoaderBlock)
├── 初始化 I/O 管理器内部数据结构
├── 为已知设备创建驱动对象
├── ★ 加载启动时驱动 (Boot Drivers) ★
│   ├── 从注册表 HKLM\...\Services 获取启动驱动列表
│   ├── 加载 \SystemRoot\System32\Drivers\*.sys
│   └── 调用驱动 DriverEntry → IoCreateDriver
├── PnP 总线枚举
│   ├── 枚举 PCI/USB/ACPI 总线
│   └── 为发现的设备加载功能驱动
├── 创建设备栈 (Device Stack)
└── 初始化文件系统识别

启动驱动的加载顺序由 CmpSortDriverList + CmpResolveDriverDependencies 在 WinLDR 阶段确定,按组 (Group) 和标签 (Tag) 排序。

4.9 安全模式和 WinPE 注册 (L1855-L1976)

安全模式 : 在 HKLM\...\Control\SafeBoot 下创建 Option 键,写入 OptionValue (1=MINIMAL, 2=NETWORK, 3=DSREPAIR) 和可选的 UseAlternateShell

WinPE 模式 : 在 HKLM\...\Control 下创建 MiniNT 键,标记系统运行在 MiniNT 环境中。

4.10 电源 Phase 1 和进程管理器 Phase 1 (L1978-L1996)

c 复制代码
PoInitSystem(1);            // 电源管理 Phase 1 (ACPI 注册等)
if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);

PsInitSystem(LoaderBlock) Phase 1:

  • 完成系统进程 (System PID 4) 的初始化
  • 加载内核模式模块 (ntdll.dll, 子系统 DLL 等)
  • 准备用户模式进程创建所需的支持结构

4.11 释放 LoaderBlock (L1998-L2001)

c 复制代码
if (LoaderBlock == KeLoaderBlock) KeLoaderBlock = NULL;
MmFreeLoaderBlock(LoaderBlock);

释放所有引导加载程序分配的内存。自此以后,系统不再依赖 FreeLDR 提供的任何数据和结构------内核已经完全独立。

4.12 ★ ExpLoadInitialProcess --- 启动 SMSS (L2015-L2017)

c 复制代码
ExpLoadInitialProcess(InitBuffer, &ProcessParameters, &Environment);

这是 Phase 1 初始化中的最终目标 ------创建第一个用户模式进程:会话管理器 (SMSS)

ExpLoadInitialProcess 的详细流程:

复制代码
ExpLoadInitialProcess(InitBuffer, ...)
│
├─ 1. 分配进程参数 (ProcessParameters)
│     包含: 当前目录、DLL 搜索路径、映像路径、命令行
│
├─ 2. 分配环境变量块 (1 页)
│     包含: Path=、SystemDrive=、SystemRoot=
│
├─ 3. 构建 SMSS 映像路径
│     └─ 从 NtInitialUserProcessBuffer 获取
│        (默认: \SystemRoot\System32\smss.exe)
│
├─ 4. ★ RtlCreateUserProcess(\SystemRoot\System32\smss.exe) ★
│     └─ 这不是普通的 CreateProcess:
│         ├─ 创建第一个用户模式进程
│         ├─ 初始化 Windows 子系统 (Win32k.sys 初始化由此触发)
│         └─ 进程句柄 → ProcessInfo->ProcessHandle
│            线程句柄 → ProcessInfo->ThreadHandle
│
├─ 5. ZwResumeThread() --- 恢复 SMSS 主线程
│     (此时 SMSS 开始执行!)
│
└─ 6. 返回 Phase1InitializationDiscard

4.13 等待 SMSS 和清理 (L2019-L2053)

c 复制代码
// 等待 5 秒让 SMSS 初始化
Timeout.QuadPart = Int32x32To64(5, -10000000);  // 5 秒
Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout);
if (Status == STATUS_SUCCESS)
{
    // SMSS 在 5 秒内退出了 → 错误 → BUGCHECK
    KeBugCheck(SESSION5_INITIALIZATION_FAILED);
}
// SMSS 正常运行中 → 关闭句柄、释放内存
ZwClose(ProcessInfo->ThreadHandle);
ZwClose(ProcessInfo->ProcessHandle);
ExpInitializationPhase++;
ExFreePoolWithTag(InitBuffer, TAG_INIT);
  • 等待 SMSS 进程句柄,超时 5 秒
  • 如果 SMSS 在 5 秒内终止(STATUS_SUCCESS) → 蓝屏 SESSION5_INITIALIZATION_FAILED
  • 如果 SMSS 正常运行(STATUS_TIMEOUT) → 清理并返回

4.14 MmZeroPageThread (L2063)

c 复制代码
MmZeroPageThread();

Phase1Initialization 返回后立即调用此函数。零页线程是一个内核系统线程,负责在后台清零空闲物理页面(为后续的内存分配做准备)。此函数永不返回

复制代码
MmZeroPageThread()
└─ while(TRUE)
   {
       KeWaitForSingleObject(&ZeroPageEvent, ...);
       // 找到空闲页并清零
       MmZeroPage(...);
   }

5. 调用链总结

复制代码
KeSetPriorityThread(InitThread, 0)  [KiInitializeKernel 末尾]
  → 调度器上下文切换
  → Phase1Initialization(LoaderBlock) 开始运行
      └─ Phase1InitializationDiscard(LoaderBlock)
           │
           ├─ [1]  HalInitSystem(1, LoaderBlock)       HAL Phase 1
           ├─ [2]  启动视频 + Logo/横幅
           ├─ [3]  PoInitSystem(0)                     电源 Phase 0
           ├─ [4]  系统时间 + 时区
           ├─ [5]  KeStartAllProcessors() (SMP)        AP 处理器启动
           ├─ [6]  执行体 Phase 1 (Ob, Ex, Ke, Kd, Se, Mm, Cc, Cm, ...)
           ├─ [7] ★ IoInitSystem(LoaderBlock) ★         I/O 管理器 + 启动驱动
           ├─ [8]  安全模式/WinPE 注册
           ├─ [9]  PoInitSystem(1)                     电源 Phase 1
           ├─ [10] PsInitSystem(LoaderBlock)            进程管理器 Phase 1
           ├─ [11] MmFreeLoaderBlock(LoaderBlock)       释放引导加载程序
           ├─ [12] ★ ExpLoadInitialProcess() ★         启动 SMSS.EXE
           ├─ [13] ZwWaitForSingleObject(SMSS, 5s)     等待 SMSS
           └─ [返回]
      └─ MmZeroPageThread()                            零页线程 (永不返回)

6. SMSS 启动后的后续初始化

当 SMSS (Session Manager Subsystem) 获得 CPU 控制权,它执行以下操作:

复制代码
smss.exe
├─ 初始化注册表 (加载更多配置单元)
├─ 创建系统环境变量
├─ 启动 \SystemRoot\System32\csrss.exe  (Windows 子系统)
├─ 启动 \SystemRoot\System32\winlogon.exe (登录管理器)
│   └─ winlogon.exe
│       ├─ 启动 \SystemRoot\System32\services.exe (服务管理器)
│       ├─ 启动 \SystemRoot\System32\lsass.exe   (安全认证)
│       └─ 显示登录界面
│
├─ 一旦成功后,smss.exe 进入等待状态
└─ (WinLogon 继续初始化 → 桌面 → 用户登录)

7. 设计要点

7.1 Phase 0/1 的分段设计

特性 Phase 0 (空闲线程) Phase 1 (Phase1Initialization 线程)
运行上下文 空闲/引导线程 真正的系统线程
可以等待 I/O
HAL 级别 HAL Phase 0 (轻量) HAL Phase 1 (完整)
I/O 系统 IoInitSystemPreDrivers IoInitSystem (全功能)
可中断 不可 (HIGH_PRIORITY) 可 (但有最高优先级)
显示 启动 Logo + 进度条

7.2 加载驱动是 Phase 1 的关键

IoInitSystem 是唯一能加载功能驱动的地方,因为它需要:

  • 完整的 I/O 管理器数据结构
  • 可等待的事件/同步对象
  • 分页池和非分页池已就绪
  • 注册表已可查询 (CmInitSystem1 已完成)

7.3 SMSS 作为第一个用户模式进程

SMSS 被选为第一个用户模式进程是因为它是 Windows 子系统的会话管理器:

  • 它负责创建 CSRSS (Client-Server Runtime Subsystem)
  • CSRSS 提供了 Win32 子系统 API
  • 只有在 Win32 就绪后,其他 Windows 程序才能运行

7.4 5 秒超时的意义

ZwWaitForSingleObject(SMSS, 5s) 的超时设计确保了:

  • 如果 SMSS 立即崩溃(映像损坏、配置错误),5 秒内终止 → SESSSION5_INITIALIZATION_FAILED 蓝屏
  • 如果 SMSS 正常运行,它会保持存活 → 超时触发,内核继续关闭句柄并清理

7.5 释放 LoaderBlock 的时机

在整个初始化链中最晚释放 LoaderBlock 的原因:

  • Phase 0 (KiInitializeKernel → ExpInitializeExecutive) --- 需要 LoaderBlock 获取内存映射、注册表基址
  • Phase 1 前半段 --- 需要 LoaderBlock 获取启动选项、启动驱动列表、NLS 数据
  • 直到 PsInitSystem Phase 1 完成之后 --- 内核已经完全自给自足,不再需要引导加载程序的任何数据
相关推荐
2401_8275012813 小时前
51单片机(二):GPIO、中断、定时器与PWM
单片机·嵌入式硬件·51单片机
尼喃15 小时前
HDMI/DP高速差分接口ESD保护:0.3pF超低电容PWESD-5VSDF方案详解
嵌入式硬件
ACP广源盛1392462567315 小时前
GSV6155@ACP# 搭配 AI 服务器、AI PC 完整适配方案
大数据·服务器·人工智能·分布式·单片机·嵌入式硬件
Saniffer_SH16 小时前
NAND技术(二):从 Channel、Die/LUN、P/E Cycle 到 LDPC,一次讲透 NAND 里那些最容易误解的概念
人工智能·驱动开发·嵌入式硬件·测试工具·fpga开发·计算机外设·压力测试
辰哥单片机设计17 小时前
STM32音乐播放器
stm32·单片机·嵌入式硬件
周洲083017 小时前
STM32 串口指令控制系统|上位机下发命令控制 LED、继电器,通用指令解析框架
stm32·嵌入式硬件·mongodb
集芯微电科技有限公司18 小时前
PC3100H 专为TFT-LCD面板偏置电源设计双输出100m电流
人工智能·单片机·嵌入式硬件·神经网络·生成对抗网络
广州灵眸科技有限公司19 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) 系统操作-线进程操作
数据库·单片机·嵌入式硬件·算法·php
集芯微电科技有限公司20 小时前
各种大小尺寸TFT-LCD面板供电偏压电源方案IC
人工智能·单片机·嵌入式硬件·神经网络·生成对抗网络