处理模型

Linux kernel 的启动包括很多组件的初始化和相关配置,这些配置参数一般是通过command line 进行配置的。在进行后续分析之前,先来理解一下command line 的处理模型:
要处理的对象是一个字符串,其中包含了各种配置信息,通常各个配置之间通过空格进行分离,每个配置的表达形式是如:param=value1,value2或者很简单就是一个rw 。
那么kernel 就需要提供对这些参数进行处理的处理函数列表。根据参数的作用以及执行期的先后不同,这些处理函数被定义到不同的段中。针对每一个参数,Kernel 都会到相应的段中查找相应的处理函数,最终进行各个组件的配置。

1 配置格式

常见的配置格式如:
 
console=ttySAC0,115200 root=nfs nfsroot=192.168.1.9:/source/rootfs initrd=0x10800000,0x14af47

2 配置方式

2.1 Bootloader动态配置

由bootloader 进行参数配置,command line 将做为atag_list 的一个节点传递到Kernel 。

2.2 Kernel 静态配置

通过make menuconfig 进行配置:运行后配置boot options->Default kernel command string 。该配置将被静态编译到Kernel 中,通过变量default_command_line 访问。

3  解析配置

3.1 相关定义

根据执行的先后顺序,可以将处理函数分为三个大类,他们分别存在于下面三个段中(参考top/arch/arm/kernel/vmlinux.lds ):
 
__setup_start = .; *(.init.setup) __setup_end = .;
 
__early_begin = .; *(.early_param.init) __early_end = .;
 
__start___param = .; *(__param) __stop___param = .;

 
这三个段内存储的不是参数,而是command line 参数所需要的处理函数。

3.1.1 .early_param.init段

“.early_param.init ” 所定义的处理相对靠前一些,它所处理的参数例如:initrd= ,cachepolicy= ,nocache , nowb , ecc= , vmalloc= , mem= ,等等。
这些处理函数是通过__early_param宏来定义的,例如:
static void __init early_initrd(char **p)
{ …… }
__early_param("initrd=", early_initrd);
对于宏__early_param,可以在top/arch/arm/include/asm/Setup.h 中找到如下定义:
 
struct early_params {
    const char *arg;
    void (*fn)(char **p);
};
#define __early_param(name,fn) \
static struct early_params __early_##fn __used \
__attribute__((__section__(".early_param.init"))) = { name, fn }
 
3.1.2 .init.setup
“.init.setup ”定义的处理则要靠后一些,它所处理的参数例如:nfsroot= , ip= ,等等。
这些处理函数是通过__setup宏来定义的,例如:
 
static int __init nfs_root_setup(char *line)
{ …… }
__setup("nfsroot=", nfs_root_setup);
 
对于宏__setup,可以在top/include/linux/Init.h 中看到:
 
#define __setup_param(str, unique_id, fn, early) \
    static char __setup_str_##unique_id[] __initdata __aligned(1) = str; \
    static struct obs_kernel_param __setup_##unique_id \
           __used __section(.init.setup) \
           __attribute__((aligned((sizeof(long))))) \
           = { __setup_str_##unique_id, fn, early }

#define __setup(str, fn) \
    __setup_param(str, fn, fn, 0)

/* NOTE: fn is as per module_param, not __setup! Emits warning if fn
 * returns non-zero. */
#define early_param(str, fn) \
    __setup_param(str, fn, fn, 1)

 
注意看的话,可以看到还有一个宏early_param ,它与宏__setup的定义相似,只不过最后一个宏参数是1 而不是0 。1 表示需要提前处理的参数。

3.1.3 __param 段

这个段中保存的是build-in 类型module 的配置参数。该宏直接用来修饰需要的变量。

3.2  解析

3.2.1 相关变量

相关的变量包括:
default_command_line
保存memuconfig 配置的参数,如果bootloader 传入了命令行参数,那么这个新的配置将被更新到该变量中。
boot_command_line
存在于.init.data 段。最初是default_command_line 的拷贝。
command_line
存在于.init.data 段。在parse_cmdline() 中被赋值,数据来源是default_command_line 。
saved_command_line
用于保存没有处理过的命令行参数,是boot_caommand_line 的拷贝。
static_command_line
是command_line 的拷贝。

3.2.2 主要函数

函数名称:parse_cmdline()
操作数据:default_command_line
函数列表: .early_param.init 段(在__early_begin 和__early_end 之间)。
函数功能: 依据函数列表对default_command_line 中的参数进行处理。
函数名称:parse_early_param()
操作数据:boot_command_line
函数列表: .init.setup 段中(__setup_start 和__setup_end 之间),主要是通过宏early_param定义的部分。
函数功能: 依据函数列表对boot_command_line 中的参数进行处理。
注意parse_one() 的第四个入参是0 ,而且第五个参数是NULL 。这里没有给出参数队列,不会对boot_command_line 的每个参数在参数队列中进行对比查找,而是直接在do_early_param() 中进行条件判断,如果满足下面的条件,那么对该参数进行对应的操作:
if ((p->early && strcmp(param, p->str) == 0) ||
                  (strcmp(param, "console") == 0 &&
                   strcmp(p->str, "earlycon") == 0)
              )
函数名称:parse_args()
操作数据:static_command_line
函数列表: __param 段(__start___param 和__stop___param 之间)。
函数功能: 该操作将依据函数列表,对static_command_line 中的参数进行相应的操作。这个操作在parse_one() 的第一部分代码完成:
for (i = 0; i < num_params; i++) {
          if (parameq(param, params[i].name)) {
                 DEBUGP("They are equal! Calling %p\n",
                        params[i].set);
                 return params[i].set(val, &params[i]);
          }
   }
接下来对于不被这个列表所支持的参数,将在unknown_bootoption() 中进行处理。在unknown_bootoption() 中主要是obsolete_checksetup() 的操作。
函数名称:obsolete_checksetup()
操作数据:static_command_line
函数列表: .init.setup 段中(__setup_start 和__setup_end 之间),主要是通过宏__setup定义的部分。
函数功能: 该操作将依据函数列表,对static_command_line 中的参数进行相应的操作。如果是在parse_early_param() 中已经处理的操作,那么这里不再处理;如果是查找到的条目中没有操作函数,那么这表示是过时的数据定义(有些早期的代码,没有定义这个函数);如果不是以上两种情形,那么利用找到的函数对参数进行处理。

3.2.3图示

Linux Command Line 解析相关推荐

  1. 【The Linux Command Line】学习笔记

    以下内容参考于书籍<The Linux Command Line>,中文版本翻译项目:快乐的 Linux 命令行 终端 提示符:$ 表示普通用户,# 表示超级用户 鼠标与光标:使用光标选择 ...

  2. The Linux Command Line读书笔记(二)

    第七章: 字符展开: 通过展开,你输入的字符,在 shell 对它起作用之前,会展开成为别的字符. [me@linuxbox ~]$ echo * Desktop Documents ls-outpu ...

  3. linux bash:command,学习使用Linux Command line(Git Bash)

    了解一个新事物,一个新知识最好的方式,就是对它问问题,然后再自己寻找答案,进行解答并总结,SO...... Question: 命令行是什么? Baidu 命令提示符是在操作系统中,提示进行命令输入的 ...

  4. linux command line 利用Entrez Direct下载NCBI数据

    一.软件的安装 1.软件下载: curl    ftp://ftp.ncbi.nlm.nih.gov/entrez/entrezdirect/edirect.zip -O (熟悉curl下载文件的方法 ...

  5. matlab提示output,强制Matlab输出到命令行(Force Matlab output to command line)

    强制Matlab输出到命令行(Force Matlab output to command line) 我正在从Windows命令提示符运行MATLAB脚本: "C:\Program Fil ...

  6. linux: 命令行运行php Run PHP from the command line

    As an alternative to /opt/lampp/bin/php, to run a php script from the command line, you just need to ...

  7. Linux/Ubuntu: 命令行任务(To-Do List)管理 task - A command line todo manager

    安装: sudo apt-get install task $ task add some very important task $ task You can also install vit if ...

  8. [Linux] DSO missing from command line

    编译 FFmpeg 官方例程 gcc -o myplay demuxing_decoding.c -I /usr/local/include/ -L /usr/local/lib -lavformat ...

  9. idea 启动shorten command line too long 错误解析

    因为项目启动的命令行太长了经常是带一些vm参数或者一些依赖jar idea提供了三种方式 Select a method that will be used to shorten the comman ...

最新文章

  1. 计算机图形学入门总结!
  2. python 替换字符串中的元素
  3. oracle 实现基于函数的索引
  4. 【消息中间件】AMQPRabbitMQ工作模式
  5. EasyDarwin开源音频解码项目EasyAudioDecoder:EasyPlayer Android音频解码库(第二部分,封装解码器接口)...
  6. 图片三:numpy制作雪碧图(如何将多个图片拼接成一张图片)
  7. sql server 海量数据速度提升:SQL优化-索引(7) 【转】
  8. 2021云栖大会丨首批阿里云计算巢认证合作伙伴获得授牌,阿里云与合作伙伴共筑云上生态
  9. 服务器开发设计之算法宝典
  10. fileitem方法_FileItem类的常用方法(关于文件上传的)
  11. (51)FPGA状态机描述(四段式)
  12. 男子花41万买手镯,被店员议论“买不起” 气到要住院
  13. Android设计模式(十五)--备忘录模式
  14. SwiftUI 很难赶上 UIKit?
  15. 【Proteus仿真8086】将IO接口电路封装成子电路CCT001
  16. mybatis 依赖于jdbc_面试BAT问的最多的27道MyBatis 面试题(含答案和思维导图总结)...
  17. MySQL5.7创建数据库与添加用户、删除用户及授权、保证数据库账号安全
  18. 【Delphi】Delphi11.1 版本 Android SDK 更新步骤
  19. 16位图xxxxxxxxxxxx
  20. ctc decoder

热门文章

  1. POJ 1195 Mobile phones【 二维树状数组 】
  2. hadoop家族的各个成员
  3. ZOJ 2165 Red and Black
  4. UIScrollView实现不全屏分页的小技巧
  5. 02-15 GUCCI 我喜欢的
  6. mysql -- MAC下安装配置mysql
  7. php $start_date-sub(,PHP DateTime类常用方法总结
  8. 电脑:电脑弹窗广告三个解决方法,欢迎收藏!
  9. 前端:Vue前端开发规范,值得收藏!
  10. 硬件:关于ARM的22个常用概念!