4、PXE协议:PXE固件与BIOS/UEFI的关系、PXE启动流程
聊到网络启动,PXE协议是绕不开的核心。说白了,它就是一套让裸机通过网络加载操作系统的标准。我最早接触PXE是在一次机房批量部署的场景里,那时候一台台插U盘装系统,装到怀疑人生。后来用上PXE,效率直接翻了几倍。
今天咱们就把它拆开揉碎了讲清楚。重点看三个东西:PXE固件和BIOS/UEFI怎么配合、启动流程到底怎么走、以及UNDI和NBP这两个关键角色。
4.1 PXE固件与BIOS/UEFI的关系
先搞清楚一个概念。PXE本身不是一个独立的系统,它是嵌入在固件里的一层协议栈。你想想看,BIOS或者UEFI在初始化硬件之后,会去扫描可启动设备。如果启用了网络启动,固件就会加载PXE ROM里的代码。
这里有个细节。传统BIOS下,PXE ROM通常是一个Option ROM,大小有限,功能也比较简单。它通过INT 18h中断来触发网络启动。我遇到过一台老服务器,BIOS里的PXE ROM版本太旧,死活认不出新网卡。后来刷了固件才解决。
到了UEFI时代,情况就不一样了。UEFI本身就是一个微型操作系统,它内置了完整的网络协议栈。PXE在UEFI下是以UEFI驱动程序的形式存在的。它不再依赖实模式的中断调用,而是通过UEFI的协议接口来工作。
- BIOS下的PXE:实模式,通过INT 18h调用,ROM空间有限
- UEFI下的PXE:保护模式,通过UEFI协议接口,功能更完整
嗯,这里要注意。UEFI的PXE启动支持IPv6,而传统BIOS基本只支持IPv4。我在一个双栈网络环境里调试过,BIOS那端死活拿不到IPv6地址,换成UEFI就正常了。
4.2 PXE启动流程详解
整个流程其实就三步:拿IP、下文件、跑程序。但每一步里面都有不少门道。
4.2.1 DHCP获取IP地址
客户端开机后,网卡初始化完毕,PXE固件就开始干活了。它会广播一个DHCP Discover报文。这个报文和普通DHCP不一样,里面带了一个特殊的选项——Option 60(Vendor Class Identifier),值通常是"PXEClient"。服务器一看这个选项,就知道这是个PXE请求。
DHCP服务器回应的时候,除了分配IP地址,还必须带上几个关键信息:
- Option 54:服务器标识
- Option 66:TFTP服务器地址
- Option 67:启动文件名(比如pxelinux.0)
我个人习惯把DHCP和TFTP分开部署。DHCP用Windows Server,TFTP用Linux。这样出问题好排查。有一次客户反映启动慢,我查了半天,发现是DHCP的Option 66配成了域名,DNS解析超时。改成IP地址后,速度立马上来了。
4.2.2 TFTP下载文件
拿到IP和启动文件名之后,PXE固件会通过TFTP去下载这个文件。TFTP协议很简单,基于UDP,端口69。它没有认证,没有加密,就是纯粹的传输。所以安全性嘛,你懂的。
这里有个坑。TFTP的传输效率不高,尤其是大文件。默认的块大小是512字节,虽然可以通过Option协商调大,但很多老设备不支持。我建议启动文件尽量控制在几MB以内。如果非要传大文件,可以考虑用HTTP Boot替代TFTP,UEFI是支持的。
# 一个典型的TFTP传输过程
客户端 -> 服务器: RRQ pxelinux.0
服务器 -> 客户端: DATA (块1, 512字节)
客户端 -> 服务器: ACK (块1)
服务器 -> 客户端: DATA (块2, 512字节)
客户端 -> 服务器: ACK (块2)
...
服务器 -> 客户端: DATA (最后一块, 小于512字节)
客户端 -> 服务器: ACK (最后一块)
我曾经在一个跨三层网络的场景里调试PXE,TFTP老是超时。后来发现是中间防火墙没开UDP 69端口的高端口回包。TFTP的数据端口是动态分配的,防火墙得允许UDP 1024以上端口才行。
4.2.3 执行引导程序
文件下载到内存后,PXE固件会跳转到这个文件的入口点执行。这个文件就是NBP(Network Bootstrap Program)。它可以是pxelinux.0、grub2的core.img、或者Windows的bootmgfw.efi。
NBP一旦跑起来,PXE固件的任务就基本结束了。后续的启动逻辑由NBP接管。比如pxelinux.0会去读取配置文件,然后根据配置去下载内核和initrd。整个过程就像接力赛,PXE是第一棒,NBP是第二棒。
4.3 UNDI与NBP的概念
这两个术语经常出现在PXE的文档里,但很多人搞不清楚它们的具体作用。
4.3.1 UNDI(Universal Network Device Interface)
UNDI是PXE协议栈的最底层。它直接和网卡硬件打交道,提供统一的接口给上层调用。说白了,它就是网卡的抽象层。不管你的网卡是Intel、Realtek还是Broadcom,只要实现了UNDI接口,PXE固件就能用统一的方式操作它。
UNDI分为两种:
- 硬件UNDI:网卡厂商提供的固件实现,烧录在网卡的Option ROM里
- 软件UNDI:由PXE固件模拟实现,用于兼容没有UNDI的网卡
我记得有一次给一台老笔记本做网络启动,网卡是Broadcom的,PXE固件里没有对应的UNDI驱动。后来我刷了一个第三方固件,把软件UNDI加进去,才搞定。
4.3.2 NBP(Network Bootstrap Program)
NBP就是前面提到的引导程序。它是PXE启动流程的终点,也是操作系统加载的起点。NBP通过PXE API来获取网络资源,比如下载配置文件、内核镜像等。
常见的NBP有:
| NBP名称 | 适用场景 | 特点 |
|---|---|---|
| pxelinux.0 | BIOS + Linux | 经典,配置灵活 |
| bootx64.efi | UEFI 64位 + Windows/Linux | 标准UEFI应用 |
| grub2的core.img | UEFI + Linux | 功能强大,支持加密 |
| ipxe.efi | UEFI + 高级需求 | 支持HTTP、iSCSI |
我个人比较喜欢用iPXE。它比原版PXE功能强太多,支持HTTP下载、iSCSI启动、甚至脚本控制。有一次需要在没有DHCP的环境里做网络启动,iPXE的脚本功能帮了大忙,直接硬编码了IP和启动路径。
- UNDI是网卡的抽象层,让PXE固件能操作任何网卡
- NBP是引导程序,负责加载操作系统
- PXE固件在中间,把UNDI和NBP串联起来
4.4 PXE启动流程图
下面这张图把整个流程串起来了。从客户端开机到操作系统启动,每一步都标清楚了。
这张图把UNDI和NBP的位置标得很清楚。UNDI在底层,负责和网卡通信。NBP在上层,负责加载系统。PXE固件在中间做调度。三者缺一不可。
好了,关于PXE协议的核心内容就这些。从固件关系、启动流程到UNDI和NBP,每个环节都有它的设计逻辑。理解这些,你就能自己搭建一套稳定的网络启动环境了。