module_init, fs_initcall

ipv4内核初始化相关

已有 6249 次阅读 2009-11-4 17:55

所在文件:
net/ipv4/af_inet.c
初始化函数定义:

  1. static int __init inet_init ( void )

初始化函数调用:

  1. fs_initcall ( inet_init ) ; //#define fs_initcall(fn)                 __define_initcall("5",fn,5)

这里的fs_initcall和module_init这样的函数是一样的功能,就是给系统内核添加一个功能函数。

这个宏的定义位于inlcludelinuxinit.h中:

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

其中 initcall_t 是个函数指针类型:typedef int (*initcall_t)(void);

而属性 __attribute__((__section__())) 则表示把对象放在一个这个由括号中的名称所指代的section中。
以这个宏定义的的含义是:
1) 声明一个名称为__initcall_##fn##id的函数指针(其中##表示替换连接,);
2) 将这个函数指针初始化为fn;
3) 编译的时候需要把这个函数指针变量放置到名称为 “.initcall” level “.init”的section中(比如level=”1″,代表这个section的名称是 “.initcall1.init”)。

这些衍生宏宏的定义也位于 inlcludelinuxInit.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 , 1 s )
  4. # define   postcore_initcall ( fn )            __define_initcall ( " 2 " , fn , 2 )
  5. # define   postcore_initcall_sync ( fn )       __define_initcall ( " 2s " , fn , 2 s )
  6. # define   arch_initcall ( fn )                __define_initcall ( " 3 " , fn , 3 )
  7. # define   arch_initcall_sync ( fn )           __define_initcall ( " 3s " , fn , 3 s )
  8. # define   subsys_initcall ( fn )              __define_initcall ( " 4 " , fn , 4 )
  9. # define   subsys_initcall_sync ( fn )         __define_initcall ( " 4s " , fn , 4 s )
  10. # define   fs_initcall ( fn )                  __define_initcall ( " 5 " , fn , 5 )
  11. # define   fs_initcall_sync ( fn )             __define_initcall ( " 5s " , fn , 5 s )
  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 , 6 s )
  15. # define   late_initcall ( fn )                __define_initcall ( " 7 " , fn , 7 )
  16. # define   late_initcall_sync ( fn )           __define_initcall ( " 7s " , fn , 7 s )

因此通过宏 core_initcall() 来声明的函数指针,将放置到名称为.initcall1.init的section中,而通过宏 postcore_initcall() 来声明的函数指针,将放置到名称为.initcall2.init的section中,依次类推。
在:include/asm-generic/vmlinux.lds.h:

  1. # define INITCALLS                                                       
  2. * ( . initcallearly . init )                                          
  3. VMLINUX_SYMBOL ( __early_initcall_end ) = .;    //注意这里的__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 )
  21. # define   INIT_CALLS                                                      
  22. VMLINUX_SYMBOL ( __initcall_start ) = .;                  
  23. INITCALLS                                               
  24. VMLINUX_SYMBOL ( __initcall_end ) = .;    //还有这里的__initcall_end

最终跟踪之后这个初始化的段会在arch/x86/kernel/vmlinux.lds.S这样的体系结构中内核二进制文件结构组织的配置文件中。
而在内核Makefile文件中有这样的编译语句:

  1. vmlinux : $ ( vmlinux - lds ) $ ( vmlinux - init ) $ ( vmlinux - main ) vmlinux . o $ ( kallsyms . o ) FORCE
  2. 。。。
  3. vmlinux - lds   := arch /$ ( SRCARCH ) / kernel / vmlinux . lds
  4. 。。。

而在init/main.c 中:

  1. static void __init do_initcalls ( void )
  2. {
  3. initcall_t * call ;
  4.  
  5. for   ( call = __early_initcall_end ; call & lt ; __initcall_end ; call ++ )
  6. do_one_initcall ( * call ) ;
  7.  
  8. /* Make sure there is no pending stuff from the initcall sequence */
  9. flush_scheduled_work () ;
  10. }

该函数的调用关系如下:

  1. start_kernel --& gt ; rest_init -& gt ; kernel_thread ( kernel_init , NULL , CLONE_FS | CLONE_SIGHAND ) ;
  2. |
  3. -& gt ; kernel_init ( void * unused ) -& gt ; do_initcalls ( void )

也就是说对于所有的内核模块或是其它的以类似该形式加入到内核中的程序,都最终在内核所在的二进制文件中是有一个固定的段来存放的,而且内核在初始化的过程中也是找到这些段的地址让后做相应的加载和执行。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值