引导期间的内核选项

    Linux允许用户把内核配置选项传给引导记录,再有引导记录传给内核,以便对内核进行调整。
    start_kernel中调用两次parse_args,用于引导期间配置用户输入数据。
    parse_param是一个函数,用于解析输入的内核配置选项的参数字符串。字符串的格式为:name_variable=value。寻址特定关键字,并调用对应的函数。

注册关键字:

    用宏进行定义:
__setup(string, fn)
string表示关键字,fn表示关联的处理函数。__setup的宏定义分为两种情况
#ifndef MODULE
#define early_param(str, fn) \
__setup_param(str, fn, fn, 0)
#else /* MODULE */
#define early_param(str, fn)
#endif

即一块代码编译为模块时,__setup被忽略了。

看两个例子:
//net/core/dev.c
_setup("netdev=", netdev_boot_setup);
//net/ethernet/eth.c
__setup("ether=", netdev_boot_setup);

上面的例子也可以看出,不同的关键字可以关联到同一处理函数中。
    
     start_kernel中调用两次parse_args原因在于:内核引导选项分为两类:

    默认选项:
        大多数选项属于这一类,由__setup定义,由parse_args的第一次调用处理、
    初期选项:
        这些选项必须必其它选项更早处理。early_param(而非__setup)进行处理。early_param与__setup区别在于early_param会设置一个标识,以便内核识别。

        内核是通过__setup宏或者early_param宏来将参数与参数所处理的函数相关联起来的。我们接下来就来看这个宏以及相关的结构的定义: 
#define __setup(str, fn)					\
__setup_param(str, fn, fn, 0) #define early_param(str, fn) \
__setup_param(str, fn, fn, 1) #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 }
early_param和__setup唯一不同的就是传递给__setup_param的最后一个参数early。_setup_param定义了一个struct obs_kernel_param类型的结构,然后通过_section宏,使这个变量在链接的时候能够放置在段.init.setup。下文有.init.setup的介绍。
struct obs_kernel_param结构如下:
struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
int early;
};

   str表示key,setup_func表示handler。early类似于优先级的一个flag,因为传递给内核的参数中,有一些需要比另外的一些更早的解析。 参考下面两边分析一节:


两遍分析:

parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);

在start_kernel函数中第二次调用parse_args函数时,会检查有module_param宏填入的模块选项,这些选项会存储在kernel_param数据结构中,module_param宏会确保这些数据结构都会被存放在特定的内存区块中(__param),有指针__start___param
和__stop___param限定。



__setup_start……__setup_end:这个区域会在引导阶段结束时释放掉,用户在运行期间不能看到或修改这些选项;
__start___param……__stop___param:这个区域不会被释放,其内容会被输出到/sys文件系统,这些选项可以显示给用户。


.init.setup 内存区

有__setup()和early_param()宏定义的关键字会被放入__setup_start……__setup_end区域,只是early_param宏定义的关键字会被设置early标记。
struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
int early;
};



模块初始化代码:

每一个模块都要提供两个函数called init_module and cleanup_module。由下面两个宏指定:
module_init(XXX);
module_exit(XXX);
当前模块设计模型:
static char version[] _ _devinitdata = DRV_NAME " ... ";
static struct vortex_chip_info {
...
} vortex_info_tbl[] _ _devinitdata = {
{"3c590 Vortex 10Mbps",
... ... ...
}
static int _ _init vortex_init (void)
{
...
}
static void _ _exit vortex_cleanup (void)
{
...
}
module_init(vortex_init);
module_exit(vortex_cleanup);

基于宏标签的优化:

    Linux使用许多宏来对一些函数和数据结构设定特殊的属性。这些宏大多定义在include/linux/init.h.中。而有些宏会通知链接器把具有相同属性的代码或数据结构放到特定专用的内存区域 。 


    右侧为宏的名字。


























深入理解Linux网络技术内幕——内核基础架构和组件初始化的更多相关文章

  1. 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口

    Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...

  2. 深入理解linux网络技术内幕读书笔记(七)--组件初始化的内核基础架构

    Table of Contents 1 引导期间的内核选项 2 注册关键字 3 模块初始化代码 引导期间的内核选项 linux运行用户把内核配置选项传给引导记录,然后引导记录再把选项传给内核. 在引导 ...

  3. 深入理解linux网络技术内幕读书笔记(十)--帧的接收

    Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...

  4. 深入理解linux网络技术内幕读书笔记(二)--关键数据结构

    Table of Contents 1 套接字缓冲区: sk_buff结构 1.1 网络选项及内核结构 1.2 结构说明及操作函数 2 net_device结构 2.1 MTU 2.2 结构说明及操作 ...

  5. 深入理解linux网络技术内幕读书笔记(五)--网络设备初始化

    Table of Contents 1 简介 2 系统初始化概论 2.1 引导期间选项 2.2 中断和定时器 2.3 初始化函数 3 设备注册和初始化 3.1 硬件初始化 3.2 软件初始化 3.3 ...

  6. 深入理解Linux网络技术内幕——设备的注册与初始化(二)

    设备注册于设备除名     设备注册与设备除名一般有 register_netdev和unregister_netdev完成.这两个是包裹函数,负责上锁,真正起作用的是其调用的register_net ...

  7. 深入理解Linux网络技术内幕——用户空间与内核空间交互

    概述:     内核空间与用户空间经常需要进行交互.举个例子:当用户空间使用一些配置命令如ifconfig或route时,内核处理程序就要响应这些处理请求.     用户空间与内核有多种交互方式,最常 ...

  8. 深入理解Linux网络技术内幕——Notification内核通知表链

    为什么要有内核通知表链:     Linux由多个相互依赖的子系统组成.其中一些子系统可能需要对其他子系统的一些事件感兴趣.这样子系统之间需要一些通信机制来实现这一功能.     在接触Notific ...

  9. 深入理解Linux网络技术内幕——中断与网络驱动程序

    接收到帧时通知驱动程序     在网络环境中.设备(网卡)接收到一个数据帧时,须要通知驱动程序进行处理. 有一下几种通知机制: 轮询:     内核不断检查设备是否有话要说.(比較耗资源,但在一些情况 ...

随机推荐

  1. 1、webpack编译打包Sass编译的css进js文件

    cnpm install css-loader --save-dev    //css-loader 是将css打包进js cnpm install style-loader --save-dev   ...

  2. nohup 日志切割

    最近遇到日志切割的问题,即程序是通过命令: nohup python *.py & 放到后台执行的,这样程序的日志输出到了nohup自动生成的nohup.out文件. 问题就来了,nohup. ...

  3. tyvj 2075 [NOIP2012T5]借教室 区间更新+二分

    描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样.面对海量租借教室的信息,我们自然希望编 ...

  4. SpringMVC实现多种数据类型绑定

    绑定基本数据类型 Java基本数据类型int的默认值是0,在使用int进行url传递参数时,参数key是必须写的,其值也只能是int类型的,否则将会报错. 比如方法: @RequestMapping( ...

  5. R-CNN(Rich feature hierarchies for accurate object detection and semantic segmentation)论文理解

    论文地址:https://arxiv.org/pdf/1311.2524.pdf 翻译请移步: https://www.cnblogs.com/xiaotongtt/p/6691103.html ht ...

  6. python - 面向对象编程(初级篇)

    写了这么多python 代码,也常用的类和对象,这里准备系统的对python的面向对象编程做以下介绍. 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) ...

  7. Java基础十一--多态

    Java基础十一--多态 一.多态定义 简单说:就是一个对象对应着不同类型. 多态在代码中的体现: 父类或者接口的引用指向其子类的对象. /* 对象的多态性. class 动物 {} class 猫 ...

  8. SpringBoot导入excle文件数据

    本文主要描述,Springboot框架下上传excel,处理里面相关数据做逻辑分析,由于用到的是前后端分离技术,这里记录的主要是后端java部分,通过与前端接口进行对接实现功能 1.在pom.xml文 ...

  9. Xshell Xftp 免费版 (xshell6 评估期已过 解决办法)

    xshell6 评估期已过,因为下载的版本是evaluation版本,是有期限的. 大家可以修改为Home and school use 的版本,这样就不会出现这个提示了. 具体的操作步骤如下: 1. ...

  10. java web mysql.jar java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

    java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 折腾了一上午,找到了这错误的原因.哎……悲剧! 确认包已经被导入web工程目录. 原来是 ...