从RAM启动时Yocto根文件系统空间分配及扩容问题
解决Yocto initramfs空间不足及启动Kernel Panic问题
问题背景
基于i.MX8MPlus平台开发从RAM运行的嵌入式Yocto测试构建,通过Yocto生成包含initramfs的fitimage启动。随着initramfs功能增加,体积持续增大,此前调整INITRAMFS_MAXSIZE、IMAGE_OVERHEAD_FACTOR等Yocto变量可解决空间问题,但当前这些变量已失效。设备拥有2GB物理内存,启动后initramfs占满557MB,却仍有1GB以上空闲tmpfs空间。添加新包后编译不触发INITRAMFS_MAXSIZE报错,但启动时出现Kernel Panic,报错信息如下:
[ 10.918626] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) [ 10.926889] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.15.52 #1 [ 10.934110] Hardware name: i.MX8MPlus [ 10.940026] Call trace: [ 10.942470] dump_backtrace+0x0/0x1a0 [ 10.946138] show_stack+0x18/0x70 [ 10.949452] dump_stack_lvl+0x68/0x84 [ 10.953116] dump_stack+0x18/0x34 [ 10.956431] panic+0x160/0x30c [ 10.959485] mount_block_root+0x180/0x234 [ 10.963496] mount_root+0x178/0x198 [ 10.966984] prepare_namespace+0x130/0x170 [ 10.971081] kernel_init_freeable+0x24c/0x290 [ 10.975437] kernel_init+0x28/0x12c [ 10.978927] ret_from_fork+0x10/0x20 [ 10.982503] SMP: stopping secondary CPUs [ 10.986709] Kernel Offset: 0x80000 from 0xffff800008000000 [ 10.992192] PHYS_OFFSET: 0x40000000 [ 10.995677] CPU features: 0x00002401,20000842 [ 11.000031] Memory Limit: none [ 11.003086] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
已尝试方法:
- 增大
INITRAMFS_MAXSIZE、IMAGE_OVERHEAD_FACTOR; - 使用
IMAGE_ROOTFS_SIZE和IMAGE_ROOTFS_EXTRA_SPACE扩容; - 排查U-Boot和内核配置的空间限制但无结果。
需求:重新分配未使用的tmpfs空间给initramfs。
问题分析
该Kernel Panic并非单纯的tmpfs空间分配问题,而是initramfs加载/解压时超出了内核或U-Boot预留的内存区域,导致内核无法完整识别initramfs文件系统。Yocto的INITRAMFS_MAXSIZE仅限制编译时生成的initramfs大小,但如果内核/U-Boot在启动阶段限制了initramfs的可用内存,就会出现编译通过但启动失败的情况。
具体解决步骤
1. 调整内核initramfs相关配置
- 打开内核配置界面:
bitbake -c menuconfig virtual/kernel - 确认以下配置:
- 开启
CONFIG_BLK_DEV_INITRD=y,并将CONFIG_INITRAMFS_MAX_SIZE设为足够大的值(设为0表示无限制,或直接配置为1610612736即1.5GB); - 确保
CONFIG_PHYS_ADDR_T_64BIT=y,保证内核能识别全部2GB物理内存; - 检查
CONFIG_INITRAMFS_ROOT_UID/CONFIG_INITRAMFS_ROOT_GID配置,确保权限设置正确,不影响文件系统挂载。
- 开启
2. 修正U-Boot启动参数的initramfs内存分配
- 在U-Boot命令行执行
printenv bootargs,查看是否包含initrd参数,格式通常为initrd=0x<起始地址>,<大小>; - 若
initrd的大小参数过小,将其调整为更大的值(比如0x60000000即1.5GB),确保能容纳解压后的initramfs; - 若使用fitimage启动,执行
iminfo <fitimage地址>查看fitimage中各段大小,确保initramfs段大小与实际生成的文件匹配,避免U-Boot传递错误的大小参数。
3. 调整设备树的内存预留配置
- 打开i.MX8MPlus的设备树文件,找到
reserved-memory节点:- 检查CMA、GPU等其他预留内存区域是否占用过多空间,适当缩小这些区域的大小,为initramfs腾出内存;
- 若存在专门给initramfs预留的内存节点,调整其
size属性为更大的值(比如0x60000000)。
4. 验证Yocto变量的实际生效情况
- 执行以下命令查看
INITRAMFS_MAXSIZE的实际生效值,确认未被其他层配置覆盖:bitbake -e <你的镜像名> | grep INITRAMFS_MAXSIZE - 在
local.conf中强制配置initramfs大小:INITRAMFS_MAXSIZE = "1610612736" # 1.5GB IMAGE_OVERHEAD_FACTOR = "1.3" - 若使用高压缩算法(如lzma)导致解压后体积骤增,可暂时将
INITRAMFS_COMPRESSION改为gzip,降低解压后的内存占用。
5. 验证initramfs的实际大小
- 找到生成的initramfs文件(通常在
tmp/deploy/images/<平台>/目录下),用以下命令查看压缩前的实际大小:zcat initramfs.cpio.gz | cpio -t | wc -c - 确保该大小不超过你在U-Boot和内核中配置的预留内存。
验证方法
调整完成后,重新编译内核、U-Boot和fitimage,启动设备后:
- 执行
df -h查看根文件系统(initramfs)的大小; - 执行
free -h查看内存使用情况,确认initramfs占用空间正常,剩余tmpfs内存充足。
内容的提问来源于stack exchange,提问作者Bryce C
相关产品推荐
相关产品推荐

