您现在的位置是:首页 > 体坛时讯体坛时讯
内核的启动参数是谁拼出来的又是怎么传过去的?——bootargs全链路
烟火之旅
2026-09-20
【体坛时讯】
1123人已围观
| bootargs是Linux内核启动时的命令行参数,它告诉内核根文件系统在哪里、使用什么控制台、启用了哪些调试功能等。在U‑Boot引导过程中,bootargs通过环境变量配置,经FDT Fixup注入到设备树的chosen节点,最终被内核读取。这条链路虽然简单,但每一个环节都可能成为引导故障的根源。 |
问题场景
内核启动时提示Kernel panic - not syncing: VFS: Unable to mount root fs或控制台没有输出——这通常意味着bootargs没有正确传递到内核。bootargs是谁拼出来的?它在什么地方注入到设备树?内核又是从哪里读到的?本文追踪bootargs从U‑Boot到Linux内核的完整链路。
一、bootargs的完整生命周期

二、bootargs的配置来源
bootargs的值由多个来源拼接而成,优先级从高到低:
| 来源 | 优先级 | 设置方式 | 说明 |
| 环境变量bootargs | 最高 | setenv bootargs "..." | 手动或启动脚本设置 |
| CONFIG_BOOTARGS | 中 | defconfig中定义 | 编译时的默认值 |
| FDT中已有的bootargs | 低 | DTB中chosen节点已有 | 被上述两者覆盖 |
在RK3576上,典型的环境变量设置如下:
=> printenv bootargsbootargs=console=ttyS2,1500000root=/dev/mmcblk0p5 rootfstype=ext4 rw init=/sbin/initearlyprintk
这是一个典型的嵌入式Linux bootargs,逐段解析:
| 参数 | 含义 |
| console=ttyS2,1500000 | 控制台为串口2,波特率1500000 |
| root=/dev/mmcblk0p5 | 根文件系统在eMMC第5分区 |
| rootfstype=ext4 | 根文件系统类型为ext4 |
| rw | 以读写方式挂载根文件系统 |
| init=/sbin/init | init程序路径 |
| earlyprintk | 早期内核打印(调试用) |
三、fdt_chosen注入机制
当U‑Boot执行到image_setup_libfdt()阶段(位于OS_PREP的boot_prep_linux()内部)时,fdt_chosen()函数将bootargs写入DTB:
// common/fdt_support.c — 实际代码intfdt_chosen(void*fdt){ intnodeoffset; interr; char*str; /* bootargs字符串 */ /* 1. 查找或创建 /chosen 节点 */ nodeoffset =fdt_find_or_add_subnode(fdt,0,"chosen"); if(nodeoffset < 0) return nodeoffset; /* 2. 通过板级回调获取bootargs */ str = board_fdt_chosen_bootargs(fdt); if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1); if (err < 0) { printf("WARNING: could not set bootargs %s.n", fdt_strerror(err)); return err; } } /* 3. 配置stdout-path */ return fdt_fixup_stdout(fdt, nodeoffset);}
board_fdt_chosen_bootargs()的默认实现就是读取U‑Boot环境变量:
// common/fdt_support.c — 默认的board_fdt_chosen_bootargs__weak char *board_fdt_chosen_bootargs(void*fdt){ returnenv_get("bootargs");}
如果环境变量未设置,返回NULL,fdt_chosen()跳过bootargs写入(此时内核使用DTB中已有的bootargs或CONFIG_CMDLINE)。
注入完成后,DTB中的chosen节点内容如下:
/chosen { bootargs ="console=ttyS2,1500000 root=/dev/mmcblk0p5 rootfstype=ext4 rw init=/sbin/init earlyprintk"; stdout-path = &uart2;};
四、内核如何读取bootargs
Linux内核在启动早期,通过early_init_dt_scan_chosen()函数从DTB的chosen节点中读取bootargs:
// kernel/drivers/of/fdt.c — Linux内核(实际代码简化)int__initearly_init_dt_scan_chosen(char*cmdline){ intl, node; constchar*p; constvoid*fdt = initial_boot_params; /* 查找/chosen节点 */ node = fdt_path_offset(fdt,"/chosen"); if(node < 0) goto handle_cmdline; /* 处理initrd信息 */ early_init_dt_check_for_initrd(node); /* 读取bootargs属性 */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l >0) strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); /* 也支持CONFIG_CMDLINE作为后备 */handle_cmdline: /* 如果bootargs为空,使用CONFIG_CMDLINE */ ...}
读取到的bootargs会存入boot_command_line全局变量,内核后续的early_param()解析器会逐个解析所有参数。
五、bootargs的动态生成
在实际开发中,bootargs经常需要根据运行时条件动态生成。RK3576的启动脚本中常见以下技巧:
# 方法1:基于分区选择root参数ifmmc dev0;then setenv bootargs"console=ttyS2,1500000 root=/dev/mmcblk0p5 rootfstype=ext4 rw"else if mmc dev1;then setenv bootargs"console=ttyS2,1500000 root=/dev/mmcblk1p5 rootfstype=ext4 rw"fi# 方法2:追加调试参数setenv bootargs${bootargs}initcall_debug# 方法3:使用CONFIG_BOOTARGS作为基础,追加运行时参数setenv bootargs"${CONFIG_BOOTARGS}quiet"
六、常见bootargs示例
七、RK3576上的典型bootargs
针对不同启动方式,RK3576的bootargs也有所不同:
eMMC启动:
console=ttyS2,1500000root=/dev/mmcblk0p5 rootfstype=ext4 rw
SD卡启动:
console=ttyS2,1500000root=/dev/mmcblk1p5 rootfstype=ext4 rw
NFS网络启动(开发调试):
console=ttyS2,1500000root=/dev/nfsrw nfsroot=192.168.1.100:/srv/nfs/rootfsip=dhcp
initramfs启动:
console=ttyS2,1500000earlyprintk
(根文件系统由initramfs提供,无需root =参数)
八、调试bootargs问题
# 查看当前bootargs=> printenv bootargs# 临时修改bootargs(仅本次启动有效)=> setenv bootargs"console=ttyS2,1500000 root=/dev/mmcblk0p5 debug"# 保存修改到环境变量存储=> saveenv# 检查注入后的DTB内容=> fdt addr${fdt_addr_r}=> fdt list /chosen
九、小结
•bootargs是Linux内核的命令行参数,决定了控制台、根文件系统等关键配置
•U‑Boot通过环境变量bootargs配置,经由fdt_chosen()注入到DTB的chosen节点
•内核在启动早期从DTB中读取bootargs,解析后执行对应的初始化
•bootargs有多种来源,环境变量优先级最高
•RK3576的典型bootargs包含console、root、rootfstype、rw等参数
•调试bootargs问题时应先检查printenv bootargs,再通过fdt list /chosen确认注入结果
审核编辑 黄宇
Tags:
相关文章
- 网线测试设备测哪些参数?从NEXT到回波损耗的链路验收解析
- LP3718BSL 芯茂微|SOP8L 自供电 PSR,SEL 可调峰值电流 24W 无光耦适配器解析
- 不锈钢智能氮气储存柜 :温湿氧含量实时监测,云端联网管理
- 聚焦新北京新创作 侯磊与黄西蒙新书分享会举行
- “众神吴哥——高棉帝国的千年瑰宝”展览在长沙开展
- 宁夏贺兰山东麓半程马拉松金秋赛9月26日开跑
- 电驱系统NVH啸叫问题测试:从原理到实操全流程
- 8通道同步+1M采样率+USB直连!DAQ123如何成为桌面级数据采集的“性能小钢炮”?
- 蛋白含量比鸡蛋高,膳食纤维比燕麦更优秀!这种食材错过太可惜
- 中国男足逆转朝鲜队 张玉宁:拿下这场比赛是对每位球员的肯定
