Linux内核分析之基础知识-6

韩乔落

第6章:启动参数与配置

通过命令行和配置选项控制内核行为


本章概述

Linux 内核启动时可以通过命令行参数传递配置信息。本章详细讲解常用的启动参数、Kconfig 配置选项以及 initrd/initramfs 的使用。

参数传递方式

架构 传递方式
x86_64 boot_params.hdr.cmd_line_ptr
ARM64 设备树 /chosen/bootargs
通用 UEFI LoadOptions

6.1 内核命令行参数

6.1.1 参数传递流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 命令行参数传递和解析流程 */

/*
* 1. 引导程序设置命令行
* - GRUB: linux /vmlinuz root=/dev/sda1 ro
* - U-Boot: bootargs environment variable
* - 设备树: chosen/bootargs property
*
* 2. 内核接收
* x86: boot_params.hdr.cmd_line_ptr
* ARM64: 从 x0 寄存器指向的设备树
*
* 3. 内核保存
* boot_command_line[] 保存原始命令行
*
* 4. 内核解析
* parse_early_param() - 早期参数
* parse_args() - 标准参数
*
* 5. 模块使用
* module_param() 声明的参数
*/

6.1.2 参数解析机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* init/main.c */

void __init setup_command_line(char *command_line)
{
/*
* 保存原始命令行
*/
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);

/*
* 保存为 saved_command_line
* 用于 /proc/cmdline
*/
saved_command_line =
memblock_alloc_kernal(COMMAND_LINE_SIZE, SMP_CACHE_BYTES);
strlcpy(saved_command_line, boot_command_line, COMMAND_LINE_SIZE);
}

/* 早期参数解析 */
void __init parse_early_param(void)
{
parse_args("Booting kernel",
static_command_line,
__start___param,
__stop___param - __start___param,
-1, -1, NULL, &do_early_param);
}

/* 标准参数解析 */
static void __init parse_args(const char *doing,
char *args,
const char *param,
unsigned num,
s64 min_level,
s64 max_level,
void (*arg)(const char *param),
int (*unknown)(char *param, char *val,
const char *doing))
{
/* 解析并处理参数 */
char *param, *val;

while (*args) {
/* 分割参数和值 */
args = next_arg(args, &param, &val);

/* 查找匹配的参数 */
for (i = 0; i < num; i++) {
if (parse_one(param, val, params + i, doing))
break;
}
}
}

6.2 常用内核参数详解

6.2.1 根文件系统参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 指定根文件系统设备
root=/dev/sda1 # 设备文件
root=/dev/disk/by-uuid/xxx # UUID
root=/dev/mapper/rootvg-rootlv # LVM 逻辑卷
root=UUID=xxx # 直接 UUID
root=LABEL=rootfs # 卷标

# 文件系统类型 (可选, 通常自动检测)
rootfstype=ext4

# 挂载选项
ro # 只读挂载 (推荐)
rw # 读写挂载
rootflags=data=writeback # ext4 数据日志模式

# 等待根设备
rootwait # 等待根设备就绪
noinitrd # 不使用 initrd

6.2.2 控制台参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 串口控制台
console=ttyS0,115200n8 # 串口0, 115200波特, 8位, 无校验
console=ttyS1,9600n8 # 串口1, 9600波特
console=ttyAMA0,115200n8 # ARM 串口

# VGA 控制台
console=tty0 # VGA 控制台
console=tty1 # 特定虚拟终端

# 多个控制台 (输出到多个设备)
console=ttyS0,115200 console=tty0

# 早期控制台
earlyprintk=serial,ttyS0,115200 # 早期串口输出
earlycon=uart,mmio,0x3f8,115200n8 # UART 早期控制台
earlycon=pciserial,mmio,0x1234,115200 # PCI 串口

# 调试级别
loglevel=7 # 内核日志级别 (0-7, 7最详细)
quiet # 减少启动输出
debug # 启用调试信息
ignore_loglevel # 忽略默认日志级别

6.2.3 CPU 参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# CPU 数量控制
maxcpus=4 # 最大使用 4 个 CPU
nr_cpus=8 # 设置 CPU 数量上限
nosmp # 禁用 SMP (单 CPU)
possible_cpus=8 # 声明可能的 CPU 数量

# 关闭/启用 CPU
additional_cpus=2 # 声明额外的热插拔 CPU

# CPU 隔离
isolcpus=1,2 # 隔离 CPU 1 和 2
nohz_full=3 # CPU 3 使用 nohz_full
rcu_nocbs=4 # CPU 4 不执行 RCU 回调

# 性能相关
performance # 启用性能模式
powersave # 启用节能模式

# x86 特定
idle=poll # 空闲时轮询而非 halt
mce=notify # MCE (机器检查异常) 通知
nmi_watchdog=0 # 禁用 NMI 看门狗

6.2.4 内存参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 内存大小限制
mem=2G # 只使用 2GB 内存
mem=512M@2G # 使用 512MB, 从 2GB 开始
memmap=2G$4G # 保留 2GB 从 4GB 开始

# 内存区域
memmap=nnK$ss # 保留内存
# 示例: memmap=128K$0x0 (保留 BIOS 区域)
# 示例: memmap=64M$0x40000000 (保留视频内存)

# slab 调试
slab_debug=Z # 开启 slab 调试

# slub 调试
slub_debug=FZP # 开启 slub 调试
# F = SLAB_DEBUG_FREE
# Z = SLAB_DEBUG_OBJECT_END
# P = SLAB_POISON

6.2.5 安全相关参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# SELinux
selinux=0 # 禁用 SELinux
selinux=1 # 启用 SELinux
enforcing=0 # SELinux 宽松模式

# AppArmor
apparmor=0 # 禁用 AppArmor
apparmor=1 # 启用 AppArmor

# 安全模块
security=selinux # 指定安全模块
security=apparmor # (或 security=tomoyo 等)

# 锁定
pax_nogaexec # PaX/grsec (如果是 PaX 补丁)

# 完整性
ima_policy=appraise_tcb # IMA 策略
evm=1 # EVM (扩展验证模块)

# 模块签名
module.sig_enforce # 强制模块签名验证

# 模块限制
module.sig_level=1 # 模块签名级别

6.2.6 虚拟化参数

1
2
3
4
5
6
7
# KVM
kvm-intel.nested=1 # Intel 嵌套虚拟化
kvm-amd.nested=1 # AMD 嵌套虚拟化
kvm.mmu.enable_audit=0 # 禁用 MMU 审计

# Xen
xen_evtchn_fifo=1 # 使用 FIFO 事件通道

6.2.7 网络参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 初始网络设备
netdev=eth0 # 初始网络设备

# 命名空间
net.ifnames=0 # 禁用可预测网络接口命名
biosdevname=0 # 禁用 BIOS 设备命名

# IPv6
ipv6.disable=1 # 禁用 IPv6
ipv6_module_auto=1 # IPv6 作为模块

# TCP
tcp_wmem="4096 65536 16777216"
tcp_rmem="4096 87380 16777216"

# 网络控制
net.core.rmem_max=16777216
net.core.wmem_max=16777216

6.2.8 调试参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 内核调试
debug # 启用一般调试
ignore_loglevel # 打印所有日志
earlyprintk=serial # 早期串口输出

# 调试选项
debug_locks_verbose=1 # 锁调试详细信息
debug_pagealloc=1 # 页分配调试
kasan=1 # KASAN (KernelAddressSANitizer)
ubsan=1 # UBSAN (UndefinedBehaviorSANitizer)

# 跟踪
trace_event=sched_switch # 跟踪调度切换
ftrace=function # 函数跟踪
ftrace_filter=funcname # 过滤跟踪函数

# kgdb
kgdbwait # 启动时等待 gdb
kgdboc=ttyS0,115200 # kgdb over 串口

# OOPS 处理
panic=10 # panic 后 10 秒重启
panic_on_oops=1 # Oops 时 panic

# kdump
crashkernel=128M # 为 kdump 保留内存
crashkernel=256M@2G # 256MB 从 2GB 开始

6.2.9 其他常用参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Init 进程
init=/sbin/init # 指定 init 进程
rdinit=/sbin/init # initrd 中的 init

# 超时
panic=5 # panic 后 5 秒自动重启

# 休眠
resume=/dev/sda2 # 从指定设备恢复
resume=UUID=xxx # 从 UUID 恢复
noresume # 禁用休眠

# 时区
tz=UTC-8 # 时区设置

# 硬件禁用
noapic # 禁用 APIC
nolapic # 禁用 LAPIC
acpi=off # 禁用 ACPI
pci=noacpi # 禁用 PCI ACPI

# ACPI 配置
acpi_osi= # 修改 OSI
acpi_debug # ACPI 调试

# 视频模式
video=vesafb:ywrap,mtrr:3,vram:32M # vesafb 参数
video=efifb # EFI 帧缓冲

# 系统管理中断
sysrq_always_enabled # 总是启用 SysRq

6.3 Kconfig 配置选项

6.3.1 启动相关配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 启动配置

# EFI 支持
CONFIG_EFI_STUB=y # EFI Stub 支持
CONFIG_EFI_MIXED=y # 混合模式 EFI
CONFIG_EFI_VARS=y # EFI 变量支持

# 内核压缩
CONFIG_KERNEL_XZ=y # XZ 压缩 (推荐)
CONFIG_KERNEL_ZSTD=y # ZSTD 压缩 (最新)

# 地址随机化
CONFIG_RANDOMIZE_BASE=y # KASLR (内核地址随机化)
CONFIG_RANDOMIZE_MEMORY=y # 内存地址随机化

# 可重定位内核
CONFIG_RELOCATABLE=y # 可重定位内核

# 5级页表 (x86_64)
CONFIG_X86_5LEVEL=y # 5级页表 (支持更多内存)

# ARM64 虚拟地址位数
CONFIG_ARM64_VA_BITS_48=y # 48位虚拟地址 (标准)
CONFIG_ARM64_VA_BITS_52=y # 52位虚拟地址

# initrd/initramfs
CONFIG_BLK_DEV_INITRD=y # initrd 支持
CONFIG_INITRAMFS_SOURCE="" # 内嵌 initramfs

# 调试信息
CONFIG_DEBUG_KERNEL=y # 内核调试支持
CONFIG_DEBUG_INFO=y # 调试信息 ( dwarf2/dwarf4 )
CONFIG_DEBUG_INFO_BTF=y # BTF (BPF Type Format)

6.3.2 设备驱动配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 网络驱动
CONFIG_NET=y # 网络支持
CONFIG_INET=y # TCP/IP 协议栈
CONFIG_NETDEVICES=y # 网络设备驱动

# 存储驱动
CONFIG_ATA=y # ATA 支持
CONFIG_SATA_AHCI=y # AHCI SATA 驱动
CONFIG_NVME_CORE=y # NVMe 核心支持

# 文件系统
CONFIG_EXT4_FS=y # ext4 文件系统
CONFIG_XFS_FS=y # XFS 文件系统
CONFIG_BTRFS_FS=y # Btrfs 文件系统
CONFIG_F2FS_FS=y # F2FS 文件系统

# 虚拟化
CONFIG_KVM=y # KVM 虚拟化支持
CONFIG_VHOST_NET=y # vhost-net

# 容器
CONFIG_NAMESPACES=y # 命名空间支持
CONFIG_CGROUPS=y # Cgroups 支持
CONFIG_NET_NS=y # 网络命名空间
CONFIG_PID_NS=y # PID 命名空间
CONFIG_USER_NS=y # 用户命名空间

6.4 initrd/initramfs

6.4.1 initrd vs initramfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌─────────────────────────────────────────────────────────────┐
│ initrd vs initramfs 对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ initrd: │
│ - 块设备格式的内存磁盘 │
│ - 需要文件系统驱动 (ext2 等) │
│ - 通过 /dev/ram 或 /dev/rd 访问 │
│ - 较旧的机制 │
│ │
│ initramfs: │
│ - cpio 归档格式 │
│ - 直接嵌入内核或作为单独文件 │
│ - 直接解压到 rootfs │
│ - 更现代的机制 │
│ - 支持动态设备加载 │
│ │
└─────────────────────────────────────────────────────────────┘

6.4.2 创建 initramfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 方法1: 使用 mkinitramfs (Debian/Ubuntu)
sudo mkinitramfs -o /boot/initrd.img-6.12.38 6.12.38

# 方法2: 使用 dracut (Fedora/RHEL)
sudo dracut -f /boot/initramfs-6.12.38.img 6.12.38

# 方法3: 手动创建
mkdir -p initramfs/bin initramfs/sbin initramfs/lib

# 复制必要的二进制文件
cp /bin/busybox initramfs/bin/

# 创建必要的设备节点
cd initramfs
mkdir dev proc sys
sudo mknod dev/null c 1 3
sudo mknod dev/console c 5 1
sudo mknod dev/ttyS0 c 4 64

# 创建 init 脚本
cat > init << 'EOF'
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev
echo "Initramfs initialized"
exec /sbin/init
EOF
chmod +x init

# 打包为 cpio
find . | cpio -o -H newc | gzip > ../initramfs.cpio.gz

6.4.3 内嵌 initramfs

1
2
3
4
5
6
# Kconfig 配置
CONFIG_INITRAMFS_SOURCE="path/to/initramfs.cpio"
CONFIG_INITRAMFS_COMPRESSION=".gz"

# 或者
CONFIG_INITRAMFS_SOURCE="" # 不内嵌, 外部提供
1
2
# 构建时会自动包含
make

6.4.4 使用 initramfs

1
2
3
4
5
6
7
8
9
10
11
12
13
# GRUB 配置
menuentry "Linux with initramfs" {
set root='hd0,gpt2'
linux /vmlinuz-6.12.38 root=/dev/sda3 ro
initrd /initrd.img-6.12.38
}

# U-Boot 配置
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2
setenv initrd_addr 0x44000000
setenv initrd_size 0x2000000
fatload mmc 0:1 ${initrd_addr} initramfs.cpio.gz
bootm ${kernel_addr} ${initrd_addr} ${fdt_addr}

6.5 模块参数

6.5.1 定义模块参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* 示例模块参数 */

#include <linux/module.h>
#include <linux/moduleparam.h>

/* 布尔参数 */
static bool debug_enable = false;
module_param(debug_enable, bool, 0644);
MODULE_PARM_DESC(debug_enable, "Enable debugging mode");

/* 整数参数 */
static int buffer_size = 1024;
module_param(buffer_size, int, 0644);
MODULE_PARM_DESC(buffer_size, "Buffer size in bytes");

/* 字符串参数 */
static char config_file[256] = "/etc/myconfig.conf";
module_param_string(config_file, config_file, sizeof(config_file), 0644);
MODULE_PARM_DESC(config_file, "Configuration file path");

/* 数组参数 */
static int ports[4] = { 0, 0, 0, 0 };
static int num_ports;
module_param_array(ports, int, &num_ports, 0644);
MODULE_PARM_DESC(ports, "Port numbers");

/* 只读参数 */
static const int version = 1;
module_param_called(version, int, &version, 0444);

6.5.2 传递模块参数

1
2
3
4
5
6
7
8
9
10
11
12
# 方式1: 加载时传递
insmod mymodule.ko debug_enable=1 buffer_size=2048

# 方式2: modprobe 配置
# /etc/modprobe.d/mymodule.conf
options mymodule debug_enable=1 buffer_size=2048

# 方式3: 内核命令行 (内嵌模块)
mymodule.debug_enable=1 mymodule.buffer_size=2048

# 方式4: GRUB 配置
linux /vmlinuz root=/dev/sda1 mymodule.debug_enable=1

6.6 sysctl 运行时配置

6.6.1 sysctl 参数

1
2
3
4
5
6
7
8
9
10
11
12
13
# 读取 sysctl 参数
sysctl kernel.hostname
sysctl net.ipv4.ip_forward

# 设置 sysctl 参数
sysctl -w kernel.hostname="newhost"
sysctl -w net.ipv4.ip_forward=1

# 配置文件
# /etc/sysctl.conf
kernel.hostname = myserver
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_source_route = 0

6.6.2 常用 sysctl 参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 内核参数
kernel.hostname # 主机名
kernel.domainname # 域名
kernel.pid_max # 最大 PID
kernel.threads-max # 最大线程数

# 内存管理
vm.swappiness # 交换倾向 (0-100)
vm.vfs_cache_pressure # VFS 缓存压力
vm.min_free_kbytes # 最小保留内存

# 网络参数
net.ipv4.ip_forward # IP 转发
net.ipv4.conf.all.rp_filter # 反向路径过滤
net.core.rmem_max # 最大接收缓冲
net.core.wmem_max # 最大发送缓冲

# 文件系统
fs.file-max # 最大打开文件数
fs.inotify.max_user_watches # inotify 监视数量

6.7 本章小结

参数配置总结

配置类型 方式 生效时机
编译配置 Kconfig 编译时
启动参数 命令行 启动时
模块参数 modprobe.conf 加载时
运行时配置 sysctl 运行时

常用场景

1
2
3
4
5
6
7
8
9
10
11
12
# 服务器场景
# /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="console=ttyS0,115200 transparent_hugepage=always"

# 桌面场景
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

# 虚拟机场景
GRUB_CMDLINE_LINUX_DEFAULT="console=hvc0 no_timer_check"

# 调试场景
GRUB_CMDLINE_LINUX_DEFAULT="debug ignore_loglevel earlyprintk=serial"
  • Title: Linux内核分析之基础知识-6
  • Author: 韩乔落
  • Created at : 2026-01-08 02:47:09
  • Updated at : 2026-01-19 13:40:39
  • Link: https://jelasin.github.io/2026/01/08/Linux内核分析之基础知识-6/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments