LINUX内核中的xx_initcall初始化标号

LINUX内核中的xx_initcall初始化标号

田海立@CSDN 2011-07-02

          LINUX内核中有很多的初始化指示标志postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall(), etc. 这些起什么作用呢?查阅源代码(android goldfish-2.6.29)并搜索网上相关文章,对此做一总结。

  1. 初始化标号

先看这些宏的定义(定义在文件include/linux/init.h中)

  1. #define pure_initcall(fn)               __define_initcall("0",fn,0) 
  2. #define core_initcall(fn)               __define_initcall("1",fn,1) 
  3. #define core_initcall_sync(fn)          __define_initcall("1s",fn,1s) 
  4. #define postcore_initcall(fn)           __define_initcall("2",fn,2) 
  5. #define postcore_initcall_sync(fn)      __define_initcall("2s",fn,2s) 
  6. #define arch_initcall(fn)               __define_initcall("3",fn,3) 
  7. #define arch_initcall_sync(fn)          __define_initcall("3s",fn,3s) 
  8. #define subsys_initcall(fn)             __define_initcall("4",fn,4) 
  9. #define subsys_initcall_sync(fn)        __define_initcall("4s",fn,4s) 
  10. #define fs_initcall(fn)                 __define_initcall("5",fn,5) 
  11. #define fs_initcall_sync(fn)            __define_initcall("5s",fn,5s) 
  12. #define rootfs_initcall(fn)             __define_initcall("rootfs",fn,rootfs) 
  13. #define device_initcall(fn)             __define_initcall("6",fn,6) 
  14. #define device_initcall_sync(fn)        __define_initcall("6s",fn,6s) 
  15. #define late_initcall(fn)               __define_initcall("7",fn,7) 
  16. #define late_initcall_sync(fn)          __define_initcall("7s",fn,7s) 
#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)

  1. __define_initcall

这些宏都用到了__define_initcall(),再看看它的定义(同样定义在文件include/linux/init.h中)

  1. #define __define_initcall(level,fn,id) \ 
  2.         static initcall_t __initcall_##fn##id __used \ 
  3.         __attribute__((__section__(".initcall" level ".init"))) = fn 
#define __define_initcall(level,fn,id) \
        static initcall_t __initcall_##fn##id __used \
        __attribute__((__section__(".initcall" level ".init"))) = fn

这其中initcall_t是函数指针,原型如下,

  1. typedef int (*initcall_t)(void); 
typedef int (*initcall_t)(void);

而属性 __attribute__((__section__())) 则表示把对象放在一个这个由括号中的名称所指代的section中。

所以__define_initcall的含义是:

1) 声明一个名称为__initcall_##fn的函数指针;

2) 将这个函数指针初始化为fn;

3) 编译的时候需要把这个函数指针变量放置到名称为 ".initcall" level ".init"的section中。


3.  放置.initcall.init SECTION

明确了__define_initcall的含义,就知道了是分别将这些初始化标号修饰的函数指针放到各自的section中的。

SECTION“.initcall”level”.init”被放入INITCALLS(include/asm-generic/vmlinux.lds.h)

  1. #define INITCALLS                                                   \ 
  2.             *(.initcallearly.init)                                  \ 
  3.             VMLINUX_SYMBOL(__early_initcall_end) = .;               \ 
  4.             *(.initcall0.init)                                      \ 
  5.             *(.initcall0s.init)                                     \ 
  6.             *(.initcall1.init)                                      \ 
  7.             *(.initcall1s.init)                                     \ 
  8.             *(.initcall2.init)                                      \ 
  9.             *(.initcall2s.init)                                     \ 
  10.             *(.initcall3.init)                                      \ 
  11.             *(.initcall3s.init)                                     \ 
  12.             *(.initcall4.init)                                      \ 
  13.             *(.initcall4s.init)                                     \ 
  14.             *(.initcall5.init)                                      \ 
  15.             *(.initcall5s.init)                                     \ 
  16.             *(.initcallrootfs.init)                                 \ 
  17.             *(.initcall6.init)                                      \ 
  18.             *(.initcall6s.init)                                     \ 
  19.             *(.initcall7.init)                                      \ 
  20.             *(.initcall7s.init) 
#define INITCALLS                                                   \
            *(.initcallearly.init)                                  \
            VMLINUX_SYMBOL(__early_initcall_end) = .;               \
            *(.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)

__initcall_start和__initcall_end以及INITCALLS中定义的SECTION都是在arch/xxx/kernel/vmlinux.lds.S中放在.init段的。

  1. SECTIONS 
  2.         .init : { 
  3.                 __initcall_start = .; 
  4.                         INITCALLS 
  5.                 __initcall_end = .; 
  6.         } 
SECTIONS
{
        .init : {
                __initcall_start = .;
                        INITCALLS
                __initcall_end = .;
        }
}

4.   初始化.initcallxx.init里的函数

而这些SECTION里的函数在初始化时被顺序执行(init内核线程->do_basic_setup()[main.c#778]->do_initcalls())。

程序(init/main.c文件do_initcalls()函数)如下,do_initcalls()把.initcallXX.init中的函数按顺序都执行一遍。

  1. for (call = __early_initcall_end; call < __initcall_end; call++) 
  2.         do_one_initcall(*call); 
        for (call = __early_initcall_end; call < __initcall_end; call++)
                do_one_initcall(*call);

*************************** 本文完 *****************************

 

来源:http://blog.csdn.net/thl789/article/details/6581146

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值