CMDLINE的解析

本文介绍Linux内核中的CMDLINE宏及其作用,并详细解释如何通过__setup宏来解析CMDLINE中的参数,同时提供了memparse函数用于处理涉及大小的参数。
         在linux的config文件中有一个特殊的宏定义CMDLINE,以前也一直在使用这个宏的参数,但是真正这个宏的解析和使用却不怎么明确。这次有机会多对它有些了解,不妨把这个浅显的认识说出来,记下来。

        到底linux kernel中是如何使用这个参数的呢?

        又为何一定要写在kernel的config文件中呢?

        对于这个参数的使用主要是通过对它的解析完成。而Linux Kernel中使用最多的处理Kernel的启动参数的函数是:__setup这条宏。当然网上关于此的解释挺多的,我也没看懂,所以也没资格谈论。

        简单的讲,这个宏的作用就是解析CMDLINE中某个字符串之后的字符串,例如以下的使用

                                               __setup("nandcfg=", nfccfg_setup);

        就是将CMDLINE宏中”nandcfg=“之后的字符串读取出来,然后进行解析使用。当然此处完全可以参考内核中原有的对于CMDLINE的解析文件来做。

        另外,如果涉及到大小的参数,可以使用如下的函数完成解析:
kernel/include/linux/kernel.h

extern unsigned long long memparse(const char *ptr, char **retptr);

<think>我们正在讨论的是系统启动过程中解析内核命令行参数(cmdline)的时间点。用户提供的引用中提到了/proc/<pid>/cmdline文件,该文件包含了启动进程的完整命令行参数。但是用户的问题是关于系统解析cmdline的时间,这里应该是指内核启动时解析由bootloader传递的内核命令行参数(kernel command line)的时间。 在Linux系统启动过程中,内核命令行参数是由bootloader(如GRUB)传递给内核的。内核在启动的最早期就会解析这些参数。具体来说: 1. 内核的入口点是arch/x86/boot/header.S(以x86架构为例)中的_start,然后会跳转到实模式代码,最后进入保护模式。 2. 在初始化过程中,内核会调用parse_early_param()和parse_args()等函数来解析命令行参数。 具体步骤: - 在实模式初始化(arch/x86/boot/main.c)中,会调用go_to_protected_mode()进入保护模式。 - 进入保护模式后,会继续执行arch/x86/kernel/head_32.S(或head_64.S)中的代码,然后跳转到start_kernel()(位于init/main.c)。 - 在start_kernel()函数中,会调用setup_arch()进行架构相关的初始化,其中就包括解析早期命令行参数(early command line parameters)。 - 在setup_arch()中,会调用parse_early_param()来解析需要早期处理的参数(例如"console="等)。 - 之后,在start_kernel()中还会调用parse_args()来解析其他命令行参数。 因此,内核命令行参数的解析发生在内核启动的早期阶段,具体在start_kernel()函数中,而且分为早期解析和普通解析两个阶段。 需要注意的是,用户提供的引用[1]中提到的/proc/<pid>/cmdline文件是进程创建后由内核维护的,它保存了启动该进程时使用的命令行字符串。每个进程都有这样一个文件。而内核启动时的命令行参数解析是在内核初始化的最开始阶段,远在用户空间的init进程启动之前。 另外,引用[2]中提到的uvm_cmdline_processor是UVM(Universal Verification Methodology)中的一个类,用于处理仿真时传递给测试平台的命令行参数,这与操作系统的内核命令行参数解析无关。 总结: 系统(内核)解析cmdline(内核命令行参数)的时间是在内核启动的早期,具体发生在start_kernel()函数中,分为两个阶段: 1. 早期解析(parse_early_param):处理需要在其他子系统初始化之前就设置的参数。 2. 主要解析(parse_args):处理其他大多数命令行参数。 这个解析过程在用户空间第一个进程init启动之前完成。 因此,我们可以这样回答: 在内核启动过程中,命令行参数(cmdline)的解析发生在内核初始化的早期阶段,具体在`start_kernel`函数中。解析分为两个步骤: 1. **早期参数解析**:在`setup_arch`函数中调用`parse_early_param`来解析需要在内存管理、调度等子系统初始化之前设置的参数(如`console=`、`earlyprintk=`等)。 2. **常规参数解析**:在`start_kernel`函数中调用`parse_args`来解析其他参数。 解析完成后,这些参数将影响内核的初始化行为。 注意:这里的内核命令行参数是由bootloader(如GRUB)传递给内核的,位于内核镜像头部信息中,通常存储在`boot_params`结构体里。 生成相关问题: 1. 内核启动过程中,命令行参数是如何从bootloader传递到内核的? 2. 如何在内核模块中获取命令行参数? 3. 常用的内核命令行参数有哪些? 由于用户要求使用中文回答,并且按照格式要求,我们这样组织: </think>在 Linux 系统启动过程中,内核命令行参数(cmdline)的解析发生在内核初始化的最早阶段,具体时间点为: ### 内核命令行解析的关键时间点 1. **引导加载程序阶段** Bootloader(如 GRUB)将包含命令行参数的内核映像加载到内存 命令行参数以字符串形式传递给内核映像(如:`console=ttyS0,115200 root=/dev/sda1`) 2. **内核入口阶段(实模式)** CPU 跳转到内核入口点 `arch/x86/boot/header.S`(x86 架构) 实模式代码从内存中提取命令行参数并存储到 `boot_params.hdr.cmd_line_ptr`[^1] 3. **保护模式初始化** 在 `arch/x86/kernel/head_64.S`(64位系统)中: ```c movq boot_params(%rip), %rsi movq boot_params+8(%rip), %rsi // 命令行指针 ``` 将命令行指针保存到全局变量 `boot_command_line` 4. **早期参数解析(`start_kernel()`)** 在 `init/main.c` 的 `start_kernel()` 函数中调用: ```c setup_arch(&command_line); // 架构相关初始化 parse_early_param(); // 解析早期参数 ``` - 关键函数调用栈: `parse_early_param()` → `parse_args()` → `do_early_param()` 5. **参数生效时序** | 解析阶段 | 时间点 | 处理参数示例 | |----------|-----------------------|--------------------------| | 超早期 | BIOS 后立即 | `mem=`, `reservelow=` | | 早期 | `setup_arch()` 期间 | `console=`, `initrd=` | | 主解析 | `kernel_init()` 之前 | `root=`, `quiet`, `splash` | ### 验证方法 1. **查看运行时参数** ```bash cat /proc/cmdline # 显示当前使用的完整命令行参数 ``` 2. **调试内核启动** 添加 `earlyprintk` 参数观察解析过程: ```bash # GRUB 配置 linux /vmlinuz ... earlyprintk=serial,ttyS0,115200 ``` 3. **内核源代码参考** - 参数存储结构:`struct boot_params`(`arch/x86/include/uapi/asm/bootparam.h`) - 解析逻辑:`parse_early_param()`(`init/main.c`)[^1] > 整个过程在用户空间初始化(`/sbin/init`)之前完成,通常在通电后 **50-300ms** 内结束(依赖硬件)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值