首先需要理清楚几个概念:pxe, ipxe, pxelinux,以及几个名词:pxelinux.0, ipxelinux.0* pxe是一个协议,跟mbr是一个性质的东西,它规定了CPU启动后通过什么方式获取引导代码并执行。* pxe的实现有许多,不同的厂商有不同的实现。并且pxe的实现代码主要有两种存放位置,一种是存在主板上,一种是存在网卡里,现在新的网卡一般都自带了pxe的实现代码。(去mbr查找引导代码的实现是在主板上的。)* 由于pxe协议比较“落后”,仅支持tftp传输数据,性能差,灵活性也差,于是有了gpxe这个项目。gpxe是一种兼容pxe的实现,并且在pxe之上增加了许多特性,例如通过http/ftp等协议传输数据。* gpxe原先使用的域名的拥有者突然收回了该域名的使用权,于是这些人fork出去做了ipxe,gpxe现在已经不再开发,ipxe开发非常活跃。* 一些较新的intel的网卡里都带了gpxe的实现代码,最新的可能会带ipxe代码。* pxelinux是syslinux项目的一个部分,syslinux主要有三个产出,syslinux、isolinux、pxelinux,分别用于硬盘、光盘、网络启动,它的角色与grub相同。* *.bin 和 *.0 文件一般是一样的,不过使用上有一些区别,下面解释* pxelinux.bin 是 pxelinux 编译后生成的文件* 由于大多数网卡、主板都不自带gpxe/ipxe的代码,所以通常引导时需要这样的途径: pxe -> ipxe -> pxelinux.bin,后面这两步可以合并,于是大家就把ipxe与pxelinux.bin的代码合体,做成了 ipxelinux.0 (gpxe+pxelinux.bin = gpxelinux.0)。一般习惯上裸的pxelinux镜像用.bin后缀,加上gpxe/ipxe之后用.0后缀。此外还会有.lkrn后缀,这是ipxe的东西,ipxe的代码默认只能通过pxe协议的方式加载,他们搞了另外一个代码入口,使得可以通过像linux kernel的方式一样加载(就是可以通过grub引导),这种镜像的后缀是lkrn.* 所以可行的引导过程可以有这些:- pxe(网卡) -> ipxe -> pxelinux.bin -> menu.c32- pxe -> ipxelinux.0 -> menu.c32- pxe -> syslinux.bin -> ipxe -> pxelinux.bin -> menu.c32- pxe -> syslinux.bin -> ipxelinux.0 -> menu.c32- grub -> ipxe.lkrn -> pxelinux.bin -> menu.c32- grub -> ipxelinux.lkrn -> menu.c32- ipxe(烧入网卡) -> pxelinux.bin- ...由于pxe代码是主板、网卡自带的,所以兼容性最好(至少本机的代码兼容本机的设备)。而ipxe兼容性略差(只是相对来说,因为我们编译时可能会漏掉一些网卡,或者一些特殊问题不好解决),曾经尝试过直接一步 pxe -> ipxelinux.0,但是发现有一些机器无法启动,加载ipxe之后就停住了。所以后来退而求其次,用两步加载,对于ipxe不支持的设备,可以在第一步pxe->pxelinux.bin之后手快一些按任意键中断,然后仍然可以使用pxe,不过之后我们一直没有维护通过tftp加载的pxelinux以及配置文件,所以那部分内容其实现在都已经严重过时了。
--
问个小白问题,为什么不能让 PXE 用 tftp 协议加载 pxelinux.bin,然后 pxelinux.bin 加载 menu.c32 模块,显示菜单呢?感觉这里绕来绕去就是为了使用 http 协议。tftp 协议真的那么不好吗?我看了一下,tftp 的文件传输部分相当于窗口大小恒定为 1、数据包大小恒定为 512 字节的 TCP 协议。在学校里毫秒级的延迟情况下,几十 KB 的 pxelinux.bin 只要 100~200 毫秒就能下载完。tftp 也是支持文件名的,为什么说 “灵活性差”?
2014-06-20 0:28 GMT+08:00 Bojie Li <boj...@gmail.com>:问个小白问题,为什么不能让 PXE 用 tftp 协议加载 pxelinux.bin,然后 pxelinux.bin 加载 menu.c32 模块,显示菜单呢?感觉这里绕来绕去就是为了使用 http 协议。tftp 协议真的那么不好吗?我看了一下,tftp 的文件传输部分相当于窗口大小恒定为 1、数据包大小恒定为 512 字节的 TCP 协议。在学校里毫秒级的延迟情况下,几十 KB 的 pxelinux.bin 只要 100~200 毫秒就能下载完。tftp 也是支持文件名的,为什么说 “灵活性差”?tftp主要有两个问题:* 下载速度非常慢,大概只有2MB/s的速度。以前用tftp的时候,加载一个debian installer initrd.gz要10s左右,图书馆查询机当时是一个rootfs.tgz(100MB左右)通过tftp加载,速度就更加不能忍了。下面是我在千兆内网做的测试:$ tftp 192.168.10.150tftp> get zeroReceived 104857600 bytes in 51.7 seconds
* tftp的服务端很弱。换成http之后,配置文件一类的东西就可以“动态化”,后端可以用php、python等,于是可以做更多的事情,例如根据客户端ip返回不同的内容,根据客户端的mac返回不同的内容(例如可以允许每个用户自定义自己的菜单),一旦后端可以动态化,那么可以玩的事情就很多了。
用 TFTP 加载大文件当然不行啦,因为 TFTP 是一个“停等”协议,上个数据的确认不到,下个数据就不能发,如果有 2 MB/s 的速度,512 字节一个包,说明每秒能传 4 K 个包,也就是往返延迟(RTT)只有 0.25 ms,这非常好啦。但我质疑的是用 pxe 加载 pxelinux,中间为什么要加入 ipxe 一步。用户选择菜单之后,pxelinux 加载的应该是操作系统的内核和 initrd,wheezy 的 netboot 分别是 2.8 MB 和 10.7 MB,这种大小的文件确实不适合 tftp 协议了。不过 pxelinux 应该能实现 HTTP 协议吧,由于多了个 TCP,开发起来可能比 tftp 麻烦一些。
* tftp的服务端很弱。换成http之后,配置文件一类的东西就可以“动态化”,后端可以用php、python等,于是可以做更多的事情,例如根据客户端ip返回不同的内容,根据客户端的mac返回不同的内容(例如可以允许每个用户自定义自己的菜单),一旦后端可以动态化,那么可以玩的事情就很多了。我觉得这纯粹是为了用上 FastCGI 吧。像我这种裸写 socket 的,实现 TFTP 和 HTTP 的难度感觉差不多,TFTP 走的是 UDP/IP,当然也能看到客户端 IP、MAC。
简单的说是的。复杂的说,http是一个广泛应用的协议,使用http,那后端就爱干啥干啥了,反正给一个url,吐一堆数据就行了,甚至bash脚本都可以做后端。而tftp做不到这一点(如果要做,基本上就是自己实现一个tftp server了,而不像http应用那样,http本身由库解决,开发者仅关注业务逻辑)。另外,通过tftp并不能一定看到客户端的mac地址,因为有NAT。HTTP也是无法看到的,但配合ipxe就可以实现,ipxe可以读到mac地址,在请求配置文件时将mac地址作为参数就可以了。之前我维护的那一版的ipxe请求boot.php时都是带着mac地址的,虽然一直没有用上。(之前有一个想法是,对于一个live系统,可以提供多个内核,分别为不同vendor的电脑优化,客户端请求时,可以根据mac地址大致的确定vendor,并返回一个合适的内核。)
pxelinux也是最近(大概去年的样子吧)才实现了自己的HTTP协议栈,也就是前面说的lpxelinux.bin,以前都是不带http协议栈,因此依赖于ipxe。
根据 MAC 地址的前三个字节(OUI)查到的是网卡的 vendor 吧,怎么查到机器的 vendor?
操作系统(如 Debian netboot installer)的内核是 ipxe 还是 pxelinux 负责加载?ipxe 启动 pxelinux 之后,pxelinux 还能调用 ipxe 的 http 模块下载文件吗?
可以的。在 ipxe shell 中执行 config 命令,能看到一堆系统变量,包括主机的信息。网上的文档中应该也有描述。
另外,ipxe 可以使用 undi,也就是通用的网卡驱动,这是 pxe 协议的一部分(但似乎是可选的?不记得了……)。所以 ipxe 可以不依赖具体网卡驱动。
另外……
我见过一个软件包,可以用来干这事:
一 、启动一个 Linux 系统,作为 loader
二、在这个作为 loader 的 Linux 系统上通过 kexec 引导真正要启动的系统。
如果最终启动的系统只有 Linux,有什么方案灵活性比这个强么……