e820_table 为空的情况

e820_table确实存在为空的情况。这种情况虽然不常见,但并非不可能,其根源在于引导程序(Bootloader)没有将内存映射信息传递给内核。

核心原因:引导程序未传递内存映射

e820_table中的数据,是由引导程序(如 GRUB)在启动时,通过调用 BIOS 中断(如INT 0x15)或从 UEFI 固件获取,然后填充到struct boot_params中的。

如果引导程序没有完成这个“传递”动作,那么内核在启动时就会收到一个空的 E820 表。例如,像linld这样的引导程序,就曾被报告存在这个问题。

内核的应对:备选方案与修复

e820_table为空时,内核无法从中获取内存信息,就会导致启动失败,例如出现内存分配死锁等问题。

为了应对这种情况,内核有一套备选机制。它不会完全依赖 E820 表,还会尝试其他传统方法获取内存大小,例如调用 BIOS 的0x88功能。

历史上,内核曾因一次代码修改(commit 157266edcc56)而意外移除了检查 E820 表是否为空的逻辑,导致备选机制被跳过,引发了在一些老旧引导程序上的启动失败。这个问题后来通过补丁修复,重新加回了对空表的检查,确保了内核能够及时回退到备选方案。

其他特殊情况

除了引导程序主动不传递信息外,E820 表本身也可能是不完整或存在缺陷的。例如,有些硬件报告的表项非常少,可能只有区区 2 项,或者存在条目顺序错乱的问题。不过,这种“不完整”和“为空”是两个概念,前者属于数据质量差,而后者是完全没有数据。对于质量差的数据,内核会在解析时尝试处理或报错,但“为空”则需要启动备选方案,否则无法获取内存信息。

总结

所以,e820_table确实存在为空的情况,它通常源于引导程序没有正确地传递内存信息。这会导致内核启动失败,除非有备选的内存探测机制作为兜底。Linux 内核开发者已经注意到了这个问题的历史影响,并通过补丁修复了相关的处理逻辑。