内核启动核心——bootargs 启动参数详解与自定义配置

📅 2026/7/19 0:24:46 👁️ 阅读次数 📝 编程学习
内核启动核心——bootargs 启动参数详解与自定义配置

内核启动核心——bootargs 启动参数详解与自定义配置

本文由黒漂技术佬原创,首发于 CSDN,转载请注明出处。

一、引言

前面我们学会了用setenv修改环境变量,今天要看的这个变量是 U-Boot 所有环境变量中的"王者"——bootargs。它决定了 Linux 内核启动后的几乎所有行为:从哪个设备挂载根文件系统、控制台输出到哪个串口、内存怎么分配、Init 进程在哪……搞不定bootargs,内核就算加载成功了也会在启动过程中 panic 挂掉。本文帮你逐个拆解bootargs的每一个重要字段。

二、bootargs 是什么?

简单说,bootargs就是 U-Boot 传递给 Linux 内核的"命令行参数"。在 PC 上,GRUB 的linux行后面的参数类似;在嵌入式设备上,这条命令由 U-Boot 在启动前设定。

一条典型的bootargs长这样:

console=ttyO0,115200n8 root=/dev/mmcblk0p2 rw rootwait

看着不长对吧?但实际工程中,bootargs可能会拉到几百个字符:

console=ttyO0,115200n8 root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4 earlyprintk ignore_loglevel coherent_pool=1M net.ifnames=0 quiet video=HDMI-A-1:1024x768-24@60 tsc=reliable

内核代码在init/main.c中解析这些参数,决定初始化路径。理解它们不是背参数列表,而是理解每一类参数在解决什么问题。

三、核心参数逐字段详解

3.1console=——内核日志出口

格式:

console=<device>,<baudrate><parity><bits>

实际示例:

console=ttyO0,115200n8console=ttyS0,115200console=ttyAMA0,115200n8console=ttySAC0,115200
参数部分含义
ttyO0串口设备名(不同 SoC 命名不同:TI 用ttyO,三星用ttySAC,普通用ttyS
115200波特率
n无校验(n=none, e=even, o=odd)
8数据位(默认8)

到底用哪个设备名?这取决于你的 SoC 的串口驱动。不确定的时候,去内核源码中搜console=tty或者在开发板的 Linux 下用dmesg | grep tty查看。

可以有多个console=

console=ttyO0,115200console=tty0

第一个是物理串口,第二个tty0是虚拟终端(LCD 屏幕)。内核会把启动日志同时输出到两个设备。

3.2root=——根文件系统在哪?

这是bootargs中最重要的参数,没有它内核连 init 进程都找不到。

块设备方式:

root=/dev/mmcblk0p2# SD 卡第2分区(eMMC 板子常见)root=/dev/mmcblk1p2# 外接 SD 卡第2分区root=/dev/sda2# U 盘第2分区root=/dev/nfs# NFS 网络根文件系统

分区 UUID 方式(推荐,避免设备名漂移):

root=PARTUUID=9e39f1f1-02root=UUID=3f8c4d2a-6b1e-4e9d-8c7a-1f2e3d4c5b6a

UUID 绑定了分区标识,不管你的 SD 卡被识别为mmcblk0还是mmcblk1,内核总能找到正确的分区。这对于产品出货非常重要——你不知道用户会插几张 SD 卡。

mtdblock 方式(NAND Flash 平台):

root=/dev/mtdblock3# 从第4个 MTD 分区启动

3.3rootfstype=——文件系统类型

rootfstype=ext4# ext4 文件系统rootfstype=ubifs# UBIFS(NAND Flash 常用)rootfstype=jffs2# JFFS2(NOR Flash 常用)rootfstype=squashfs# 只读压缩文件系统

如果不指定,内核会自己探测文件系统类型。但为了稳定性,建议明确指定。

3.4rw/ro——读写还是只读?

rw# 读写挂载根文件系统ro# 只读挂载(嵌入式设备常见,防意外写入)

很多嵌入式 Linux 产品使用ro启动,应用层需要写入时再mount -o remount,rw /,这是一种保护机制。

3.5rootwait/rootdelay=——等待根设备就绪

rootwait# 无限等待,直到根设备出现rootdelay=5# 等待 5 秒后再尝试挂载根设备

对于 SD 卡、U 盘这种检测较慢的设备,rootwait几乎是必选项,否则内核启动瞬间设备还没 ready,直接 panic。rootdelay更有控制性,但一般rootwait就够了。

3.6init=——指定 Init 进程

init=/sbin/init# 默认init=/bin/sh# 调试用,直接进 Shellinit=/usr/sbin/myapp# 自定义应用程序作为 Init

调试阶段把init=/bin/sh写进 bootargs,内核启动后直接给你一个 Shell,不需要完整的 rootfs,排查问题极方便。

四、调试与性能相关参数

4.1 内核日志控制

quiet# 减少启动日志,只显示关键信息loglevel=7# 输出所有级别日志(0=最安静, 7=最啰嗦)ignore_loglevel# 忽略所有日志限制,全输出earlyprintk# 在 console 初始化之前就用早期串口输出日志

调试内核启动问题时,把这三个参数一起上:

console=ttyO0,115200 ignore_loglevel earlyprintk

这样你就能看到最完整的内核启动日志,不会错过任何一行关键输出。

4.2 内存相关

mem=256M# 限制内核只使用 256MB 内存mem=512M@0x80000000# 从 0x80000000 开始分配 512MBvmalloc=256M# vmalloc 区域大小cma=64M# CMA(Contiguous Memory Allocator)预留

mem=用于告诉内核实际可用的物理内存大小和起始地址。如果 U-Boot 没有正确传递内存信息(ATAGS 或 DTB 中),或者你需要预留内存给硬件加速器、DSP 等协处理器,就需要手动指定。

mem=480M@0x80000000# 512M 中预留 32M 给 DSP

4.3 显示相关

video=HDMI-A-1:1024x768-24@60# HDMI 输出,1024x768,60Hzvideo=LVDS-1:800x480@60# LVDS LCD 屏

具体格式和可用设备名去看内核的Documentation/fb/modedb.txt

4.4 其他实用参数

net.ifnames=0# 使用传统网卡命名(eth0)而非 systemd 风格ip=dhcp# 内核启动阶段通过 DHCP 获取 IP(NFS root 必须)nfsroot=192.168.1.200:/nfs/rootfs,v3,tcp# NFS root 挂载参数panic=10# 内核 panic 后 10 秒自动重启

五、实际配置示例

示例1:SD 卡标准启动

setenv bootargs"console=ttyO0,115200n8 root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4"

示例2:NFS 网络启动(开发调试常用)

setenv bootargs"console=ttyO0,115200n8 root=/dev/nfs rw \ nfsroot=192.168.1.200:/nfs/rootfs,v3,tcp \ ip=192.168.1.100:192.168.1.200:192.168.1.1:255.255.255.0::eth0:off"

ip=参数的完整格式:

ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>

示例3:调试模式启动

setenv bootargs"console=ttyO0,115200n8 root=/dev/mmcblk0p2 rw \ rootwait init=/bin/sh ignore_loglevel earlyprintk"

示例4:生产环境只读启动

setenv bootargs"console=ttyO0,115200n8 root=/dev/mmcblk0p2 ro rootwait \ rootfstype=ext4 quiet loglevel=4 panic=10"

六、调试技巧:如何确认 bootargs 已生效?

在内核启动后,检查/proc/cmdline

cat/proc/cmdline# 输出应与 bootargs 一致

如果发现不一致,可能的原因:

  1. U-Boot 环境变量中bootargs没有saveenv
  2. 设备树中chosen/bootargs节点覆盖了 U-Boot 传入的值。
  3. 内核CONFIG_CMDLINE编译选项覆盖了动态参数。

七、总结

bootargs是 U-Boot 与 Linux 内核之间最重要的"对话通道",配置正确与否直接影响系统能否启动。核心记住:

  • console=决定日志去哪。
  • root=决定根文件系统从哪来。
  • rw/ro决定挂载模式。
  • rootwait是 SD 卡/eMMC 启动的护身符。
  • 调试时加ignore_loglevel earlyprintk init=/bin/sh,事半功倍。

下一篇,我们把前面学到的知识串起来,用 SD 卡、NFS、TFTP 三种方式完整地把系统跑起来。