在内核日志记录开始之前调试 grub 中的启动性能问题

she*_*heß 6 performance grub boot debugging boot-loader

我的电脑需要很长时间才能启动。我有理由相信这是由 grub 之后的延迟引起的,但在内核日志记录开始之前(启动需要 30 秒,但dmesg消息在0.00000-之间有时间戳9.34223这篇文章中有详细信息)。

有什么方法可以调试正在发生的事情吗?特别是:

  • 有没有办法让 grub 本身更详细,或者保留日志?
  • grub 和内核日志记录之间是否还有其他可能需要时间的进程?我如何调试这些?

我相信这个问题不是特定于我的设置。但以防万一,我正在运行 Ubuntu 16.10 和 grub(2)

编辑

按照@TooTea 的建议,我设置了debug=all环境变量,这些变量产生了很多script/script.c:50 malloc 0x7a9a2ca0应该不成问题的消息。然后有一个消息块与 8 秒延迟延迟一致:

kern/dl.c:56 Detecting ext2... 
lib/relocator.c:1397 chunks = 0x7a7e0ae0
lib/relocator.c:434 trying to allocate in ...-... aligned ... size ...
lib/relocator.c:1198 allocated: ...+...
lib/relocator.c:1409 allocated .../...
lib/relocator.c:1410  chunks = 0x7a7e0ae0
Run Code Online (Sandbox Code Playgroud)

she*_*heß 6

这当然不是我自己问题的完整答案,但可能对其在调查类似问题时登陆此处的其他人有用。

GRUB 手册建议使用debug环境变量,或者debug=all带有设施名称的逗号/空格列表。然后它说:

有关更多详细信息,请参阅来源。

我无法在网上找到潜在名单。因此,为了将来参考,我从当前的 github 存储库 coreos/grub 中提取了这些名称的列表,希望这对我和其他人将来有用。当然,如果不进一步调查来源,这的用途是有限的,但仍然可能是一个很好的起点。

name                frequency in source
acpi                |||||
affs                |
ahci                ||
appleload           |
arcdisk             ||
archelp             ||
ata                 ||
atkeyb              ||
biosdisk            ||
bsd                 ||||
btrfs               ||
cache               ||
cbfs                |
chain               |||
crypt               ||
cryptodisk          ||
datetime            |
devalias            ||
disk                |||||
diskfilter          ||
dl                  ||||||||
dns                 ||
drivemap            ||
efi                 ||
efidisk             ||
efiemu              ||||||||||||||
ehci                ||
elf                 ||
exfat               |
expand              ||
fat                 |
fb                  ||
fdt                 |
fixvideo            ||
font                ||
fs                  ||
geli                ||
gpt                 ||||
hostdisk            |||||
init                |||||
jpeg                |
keystatus           ||
lexer               |
linux               |||||||||||||
loader              |||||||
luks                ||
memdisk             ||
mm                  ||
mmap                |||||
modules             ||
multiboot_loader    |||||
nativedisk          ||
net                 ||||||||||
ohci                ||
partition           ||||||
pata                ||
play                ||
reiserfs_tree       ||
relocator           |||
scripting           ||
scsi                ||
serial              ||
smbios              ||
syslinux            ||
tftp                ||
tga                 ||
ubootdisk           ||
uhci                ||
usb                 ||||||
usb_keyboard        ||
usbms               ||
video               |||||||
xen                 |||||||||
xen_loader          ||
xfs                 ||
xnu                 ||||||
zfs                 |||||
Run Code Online (Sandbox Code Playgroud)

例如你可以写

set debug=linux,video,fs
Run Code Online (Sandbox Code Playgroud)

进入您的/boot/grub/grub.cfg以减少 GRUB 的调试冗余并仅显示这些设施的调试消息


Too*_*Tea 5

正如您可能想象的那样,GRUB 和 Linux 之间的切换涉及一些非常复杂的低级步骤,因此没有进行高级跟踪或日志记录的空间。幸运的是,这应该不是问题,因为该代码中也没有任何扩展停顿的空间。通过设置debug环境变量,您可以获得 GRUB 中所有准备步骤的非常详细的跟踪。

然而,在控制权转移到 Linux 内核之后,您看到的任何延迟都更有可能发生。通常,在控制台初始化之前您看不到日志消息。此外,正如您所指出的,在计时子系统初始化之前,所有时间戳都为零,因此以后无法确定时间。

幸运的是,您可以使用earlyprintk引导选项让内核实际在某处打印日志消息,以便您可以实时跟踪它们并查看延迟发生的位置。earlyprintk可以定向到各种目的地,但与普通(物理)机器最相关的是serialvga(老式控制台)或efi。确保您的内核是使用适当的配置选项 ( CONFIG_EARLY_PRINTK*)构建的。