U-Boot SPL 加载后续程序过程中的内存泄漏问题
问题
项目里是这样设计的 U-Boot SPL 加载过程:SPL 会从多种启动设备尝试加载 uImage。加载的顺序是由板卡支持代码里指定的:
文件:board/
u32 spl_boot_device(void)
{
return BOOT_DEVICE_MMC1;
}
void board_boot_order(u32 *spl_boot_list)
{
spl_boot_list[0] = spl_boot_device();
spl_boot_list[1] = BOOT_DEVICE_MMC2;
spl_boot_list[2] = BOOT_DEVICE_SPI;
spl_boot_list[3] = BOOT_DEVICE_NOR;
spl_boot_list[4] = BOOT_DEVICE_SATA;
}
这里的 spl_boot_list
指定了先后顺序。如果出现某个启动设备加载失败、或者加载内容不合格等等各种问题,那么就会尝试下一个启动设备,直到加载成功、并跳转到 U-Boot,或者启动失败。
开发过程中,进行了多个组合的验证,比如写坏某些启动设备里的 uImage 内容,验证是否能从后续启动设备加载并运行,等等。
现在碰到的问题是,遍历了若干个启动设备后,U-Boot SPL 出现内存不足,导致程序本身无法继续运行。
定位及解决
走读并跟踪了 SPL 代码,定位到内存泄漏出现之前的调用关系,如下:
// FILE: common/spl/spl_fit.c
spl_load_simple_fit()
struct spl_fit_info ctx;
...
spl_simple_fit_read(&ctx, ...)
void * buf = spl_get_fit_load_buffer()
buf = malloc()
...
info->read(..., buf)
...
ctx->fit = buf;
...
spl_load_simple_fit()
通过调用 spl_simple_fit_read()
分配内存并往里面写入被加载的程序,所分配的内存记录在 ctx.fit
变量里。如果 spl_load_simple_fit()
后续的代码里遇到什么问题,加载过程就会被中断、并提前返回,但这里并没有正确地释放内存,所以产生了内存泄漏。
定位到了问题,解决就容易了。查找 spl_load_simple_fit()
提前返回的地方,补上恰当的内存释放、调用 free((void *)ctx.fit);
即可。
结论
这个内存泄漏,只在板子内存特别有限、且有多种启动设备的情况下,才会出现实质性的影响。
对于大多数的情况,不会出现什么影响;并且等后续的程序接管内存后,就不再是问题。所以从U-Boot 源代码来看,这个代码一直是这样。