Linux Command Line 解析

0 处理模型

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, ¶ms[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()中已经处理的操作,那么这里不再处理;如果是查找到的条目中没有操作函数,那么这表示是过时的数据定义(有些早期的代码,没有定义这个函数);如果不是以上两种情形,那么利用找到的函数对参数进行处理。

Linux Command Line 解析的更多相关文章

  1. 《The Linux Command Line》 读书笔记04 Linux用户以及权限相关命令

    Linux用户以及权限相关命令 查看身份 id:Display user identity. 这个命令的输出会显示uid,gid和用户所属的组. uid即user ID,这是账户创建时被赋予的. gi ...

  2. 《The Linux Command Line》 读书笔记02 关于命令的命令

    <The Linux Command Line> 读书笔记02 关于命令的命令 命令的四种类型 type type—Indicate how a command name is inter ...

  3. 《The Linux Command Line》 读书笔记01 基本命令介绍

    <The Linux Command Line> 读书笔记01 基本命令介绍 1. What is the Shell? The Shell is a program that takes ...

  4. Linux Command Line Basics

    Most of this note comes from the Beginning the Linux Command Line, Second Edition by Sander van Vugt ...

  5. 15 Examples To Master Linux Command Line History

    When you are using Linux command line frequently, using the history effectively can be a major produ ...

  6. 10 Interesting Linux Command Line Tricks and Tips Worth Knowing

    I passionately enjoy working with commands as they offer more control over a Linux system than GUIs( ...

  7. Reso | The Linux Command Line 的中文版

    http://book.haoduoshipin.com/tlcl/book/zh/ 本书是 The Linux Command Line 的中文版, 为大家提供了多种不同的阅读方式. 中英文双语版- ...

  8. [笔记]The Linux command line

    Notes on The Linux Command Line (by W. E. Shotts Jr.) edited by Gopher 感觉博客园是不是搞了什么CSS在里头--在博客园显示效果挺 ...

  9. Linux Command Line(II): Intermediate

    Prerequisite: Linux Command Line(I): Beginner ================================ File I/O $ cat > a ...

随机推荐

  1. [Linq Expression]练习自己写绑定

    源代码:TypeMapper.zip 背景 项目中,我们会经常用到各种赋值语句,比如把模型的属性赋值给UI,把视图模型的属性拷贝给Entity.如果模型属性太多,赋值也会变成苦力活.所以,框架编程的思 ...

  2. java数据结构和算法------合并排序

      package iYou.neugle.sort; public class Merge_sort { public static void MergeSort(double[] array, i ...

  3. PB小技巧集锦

    1. 数据窗口检查重复行dw_1.SetSort ("user_id A")dw_1.Sort()dw_1.SetFilter ("user_id = user_id[- ...

  4. 启动级别:init 0,1,2,3,4,5,6

    这是个很久的知识点了,只是自己一直都迷迷糊糊的,今天在翻出来好好理解下.. 0:停机 1:单用户形式,只root进行维护 2:多用户,不能使用net file system 3:完全多用户 5:图形化 ...

  5. Spring集成hibernate错误

    八月 25, 2016 7:55:31 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin警告: [SetPropertiesRule ...

  6. jQuery 效果 - slideDown() 方法[菜单导航栏常用]

    实例 以滑动方式显示隐藏的 <p> 元素: $(".btn2").click(function(){ $("p").slideDown(); }); ...

  7. C++ Template之类模版

    类模版的定义和声明都和函数模版类似: 代码如下: template <typename T> class Stack { public: void push(const T&); ...

  8. html5 webApp常用Meta标签

    Html5 webApp常用Meta标签 <meta charset="UTF-8"> <meta name="viewport" conte ...

  9. PHP第一课:开发环境配置

    最近在学php,大概了解了一下php的语法结构,以及一些php及基础的知识.由此想到了要亲手试一试:以为以前是学java的用的  ide是myeclipse,所以对eclipse软件布局有特别的钟爱. ...

  10. ASP.NET输出PNG图片时出现GDI+一般性错误的解决方法

    偶原来的用ASP.NET生成验证码图片时用的是JPG格式,今天想把它改成PNG格式的,结果就出现GDI+一般性错误,查了N久资料,才发现解决的办法,对分享此解决办法的网友深表感谢 Response.C ...