内核启动组件式初始化.doc_第1页
内核启动组件式初始化.doc_第2页
内核启动组件式初始化.doc_第3页
内核启动组件式初始化.doc_第4页
内核启动组件式初始化.doc_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux内核源码中多处会看到诸如_init,_initdata,_exitdata的关键字,大部分这样的关键字定义在include/linux/init.h头文件中,它们都会在编译连接阶段被实现处理。#define _init _section(.init.text) _cold notrace _init标记的数据被存储在.init.text节#define _initdata _section(.init.data) _initdata标记的数据被存储在.init.data节#define _initconst _section(.init.rodata) _initconst标记的数据被存储在.init.rodata节#define _exitdata _section(.exit.data) _exitdata标记的数据被存储在.exit.data节#define _exit_call _used _section(.exitcall.exit) _exit_call_used标记的数据被存储在.exitcall.exit节我们也经常看到许多诸如subsystem_initcall(fn)的语句,fn为某个函数的名称,也可以在init.h中找到它的踪影。#define _define_initcall(level,fn,id) static initcall_t _initcall_#fn#id _used _attribute_(_section_(.initcall level .init) = fn#define early_initcall(fn) _define_initcall(early,fn,early)#define pure_initcall(fn) _define_initcall(0,fn,0)#define core_initcall(fn) _define_initcall(1,fn,1)#define subsys_initcall(fn) _define_initcall(4,fn,4)#define core_initcall_sync(fn) _define_initcall(1s,fn,1s).#define late_initcall_sync(fn) _define_initcall(7s,fn,7s)#define _initcall(fn) device_initcall(fn)#define _exitcall(fn) static exitcall_t _exitcall_#fn _exit_call = fn可以看出每个与_define_initcall相关的注册函数都被解释为 :static initcall_t _initcall_fn_id, 入口地址将被存储在.initcalllevel.init节中。我们常在Linux模块中用到的module_init和module_exit的真身也可以看到:#define module_init(x) _initcall(x);#define module_exit(x) _exitcall(x);init.h中还有一些代码设计boot与kernel的参数交换例如:#define _setup_param(str, unique_id, fn, early) static const char _setup_str_#unique_id _initconst _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)/* Relies on boot_command_line being set */void _init parse_early_param(void);void _init parse_early_options(char *cmdline);我们经常用到的early_param,_setup用于处理boot传递过来的参数内核启动后进入组件式初始化的过程如下图所示:组件的初始化有以下三类:1.来着bootloader传递的参数,使用do_early_param函数从_setup_start_setup_end区间搜索完成。2.中断和时钟的初始化3.普通的初始化函数,这些主要是通过do_initcalls()函数完成的。第一类初始化中,bootloader传递给kernel的参数格式为A=B,内核通过_setup和early_param标记来识别参数对应的函数。相当于我们所说的绑定。#define _setup(str,fn) _setup_param(str,fn,fn,0)#define early_param(str,fn) _setup_param(str,fn,fn,1)两者的差别就在最后一个参数,_setup_param内容如下:#define _setup_param(str,unique_id,fn,early) static char _setup_str_#unique_id_initdata_aligned1=str; static struct obs_kernel_param _setup_#unique_id /实例名称 _used_section(.init.setup) /存放到.init.setup节 _attribute_(aligned(sizeof(long) /对其要求 =_setup_str_#unique_id, fn, early 可以看出查遍就在 obs_kernel_param数据结构的early成员是否置1。再看一下obs_kernel_param的细节:struct obs_kernel_param const char *str; int (*setup_func)(char *);/slot用于绑定对应的函数 int early;/执行优先级的标记可见被early_param修饰的函数要先于被_setup标记修饰的函数,以下是两种函数的调用过程:对以early_param修饰的函数,是由do_early_param(.)一般的函数若要在内核启动时背do_early_param调用,需使用early_param(.)注册“一个典型的例子是:调试信息的的显示:在linux_cmdline中如果加入了debug那么内核启动的信息将逐一打印出来,具体实现是这样的:static int _init debug_kernel(char *str) console_loglevel = 10; return 0;earl

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论