Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2149045
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2013-09-25 16:16:46


1. initcall的执行过程
start_kernel
--> rest_init();
--> kernel_thread(kernel_init);  //产生一个线程
--> kernel_init 
    --> do_basic_setup
在init/main.c中
  1. static void __init do_basic_setup(void)
  2. {
  3.     cpuset_init_smp();
  4.     usermodehelper_init();
  5.     init_tmpfs();
  6.     driver_init();
  7.     init_irq_proc();
  8.     do_ctors();
  9.     do_initcalls();    //终于看到主角了
  10. }

start_kernel
--> rest_init();
--> kernel_thread(kernel_init);  //产生一个线程
--> kernel_init 
    --> do_basic_setup
        --> do_initcalls
在init/main.c中
extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
  1. static void __init do_initcalls(void)
  2. {
  3.     initcall_t *fn;
  4.     for (fn = __early_initcall_end; fn < __initcall_end; fn++)
  5.         do_one_initcall(*fn);
  6. }
那么__early_initcall_end又是从哪里来的呢?这个先放一下.

  1. int __init_or_module do_one_initcall(initcall_t fn)
  2. {
  3.     printk(KERN_INFO "fn=%p\n",fn);   //自己加的打印
  4.     ret = fn();          //这个fn就是一个函数地址
  5. }
当此处打印出c000e620时,
在System.map中查看-->c000e620 t s3c64xx_init_irq_eint
就是要执行s3c64xx_init_irq_eint这个函数了
2. initcall_start initcall_end等是从哪里来的
在arch/arm/kernel/vmlinux.lds中,有
  1. 437 __initcall_start = .; 
  2. *(.initcallearly.init)
  3. __early_initcall_end = .; 
  4. *(.initcall0.init)      *(.initcall0s.init)
  5. *(.initcall1.init     *(.initcall1s.init)
  6. *(.initcall2.init     *(.initcall2s.init)
  7. *(.initcall3.init     *(.initcall3s.init) 
  8. *(.initcall4.init)      *(.initcall4s.init)
  9. *(.initcall5.init)      *(.initcall5s. init
  10. *(.initcallrootfs.init
  11. *(.initcall6.init)      *(.initcall6s.init)
  12. *(.initcall7.init)      *(.initcall7s.init)
  13. __initcall_end = .
从上面可以看出在 __early_initcall_end与__initcall_end之间的就是所以的initcall(0-7)

3. 如何将函数放在initcall_start与initcall_end之间的?
以s3c64xx_init_irq_eint为例:
在arch/arm/mach-s3c64xx/irq-eint.c中
  1. static int __init s3c64xx_init_irq_eint(void)
  2. {
  3.     中间省略
  4.     return 0;
  5. }
  6. arch_initcall(s3c64xx_init_irq_eint); //在函数的最后有这么个宏
宏的定义在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)

  17. #define __initcall(fn) device_initcall(fn)
又一个宏:
  1. #define __define_initcall(level,fn,id) \
  2.     static initcall_t __initcall_##fn##id __used \
  3.     __attribute__((__section__(".initcall" level ".init"))) = fn
将arch_initcall(s3c64xx_init_irq_eint);展开后:   
static initcall_t __initcall_s3c64xx_init_irq_eint3 __used __attribute__((__section__(".initcall" 3 ".init"))) = s3c64xx_init_irq_eint
就是把s3c64xx_init_irq_eint这个函数放在了.initcall3.init这个section中


注意:这个MODULE宏很奇怪
这里的MODULE都是没有定义的,但是编译出ko来用insmode加载时,MODULE都是定义的





阅读(1761) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~