运河中央公园:系统初始化函数集(subsys_initcall)和初始化段应用

来源:百度文库 编辑:中财网 时间:2024/05/05 19:24:16

 1 系统初始化调用函数集分析(静态)1.1 函数定义 在linux内核代码里,运用了subsys_initcall来进行各种子系统的初始化,具体怎么初始化的呢?其实并不复杂。以2.6.29内核作为例子。在下就能找到subsys_initcall的定义:#define pure_initcall(fn)              __define_initcall("0",fn,0)#define core_initcall(fn)              __define_initcall("1",fn,1)#define core_initcall_sync(fn)    __define_initcall("1s",fn,1s)#define postcore_initcall(fn)      __define_initcall("2",fn,2)#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)#define arch_initcall(fn)              __define_initcall("3",fn,3)#define arch_initcall_sync(fn)    __define_initcall("3s",fn,3s)#define subsys_initcall(fn)          __define_initcall("4",fn,4)#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)#define fs_initcall(fn)                  __define_initcall("5",fn,5)#define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)#define rootfs_initcall(fn)           __define_initcall("rootfs",fn,rootfs)#define device_initcall(fn)         __define_initcall("6",fn,6)#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)#define late_initcall(fn)               __define_initcall("7",fn,7)#define late_initcall_sync(fn)      __define_initcall("7s",fn,7s)
而__define_initcall又被定义为#define __define_initcall(level,fn,id) \ static initcall_t  __initcall_##fn##id   __used \ __attribute__((__section__(".initcall" level ".init"))) = fn
所以 subsys_initcall(fn) == __initcall_fn4 它将被链接器放于section  .initcall4.init 中。(attribute将会在另一篇文章中介绍)1.2 初始化函数集的调用过程执行过程:start_kernel->rest_init系统在启动后在rest_init中会创建init内核线程init->do_basic_setup->do_initcallsdo_initcalls中会把.initcall.init.中的函数依次执行一遍:
for (call = __initcall_start; call < __initcall_end; call++) {.    .....result = (*call)();.    ........}
这个__initcall_start是在文件定义的: .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {   __initcall_start = .;   INITCALLS   __initcall_end = .;  }
INITCALLS被定义于:#define INITCALLS       \   *(.initcall0.init)      \   *(.initcall0s.init)      \   *(.initcall1.init)      \   *(.initcall1s.init)      \   *(.initcall2.init)      \   *(.initcall2s.init)      \   *(.initcall3.init)      \   *(.initcall3s.init)      \   *(.initcall4.init)      \   *(.initcall4s.init)      \   *(.initcall5.init)      \   *(.initcall5s.init)      \   *(.initcallrootfs.init)      \   *(.initcall6.init)      \   *(.initcall6s.init)      \   *(.initcall7.init)      \   *(.initcall7s.init)
2 基于模块方式的初始化函数(动态)2.1函数定义subsys_initcall的静态调用方式应该讲清楚来龙去脉了,现在看看动态方式的初始化函数调用(模块方式)。在里,如果MODULE宏被定义,说明该函数将被编译进模块里,在系统启动后以模块方式被调用。#define core_initcall(fn)         module_init(fn)#define postcore_initcall(fn)  module_init(fn)#define arch_initcall(fn)        module_init(fn)#define subsys_initcall(fn)    module_init(fn)#define fs_initcall(fn)             module_init(fn)#define device_initcall(fn)     module_init(fn)#define late_initcall(fn)         module_init(fn)这是在定义MODULE的情况下对subsys_initcall的定义,就是说对于驱动模块,使用subsys_initcall等价于使用module_init
2.2 module_init 分析下面先看看module_init宏究竟做了什么#define module_init(initfn)     \ static inline initcall_t __inittest(void)  \ /*定义此函数用来检测传入函数的类型,并在编译时提供警告信息*/ { return initfn; }     \ int init_module(void) __attribute__((alias(#initfn))); /*声明init_modlue为 initfn的别名,insmod只查找名字为init_module函数并调用*/
typedef int (*initcall_t)(void); /*函数类型定义*/
在以模块方式编译一个模块的时候,会自动生成一个xxx.mod.c文件, 在该文件里面定义一个struct module变量,并把init函数设置为上面的init_module() 而上面的这个init_module,被alias成模块的初始化函数(参考