zoukankan      html  css  js  c++  java
  • Linux内核初始化定义

    转载:http://blog.csdn.net/beatbean/article/details/8448623

    1. Compile宏控制

    位于include/linux/init.h

    [cpp] view plaincopy
     
    1. /* These are for everybody (although not all archs will actually 
    2.    discard it in modules) */  
    3. #define __init      __section(.init.text) __cold notrace  
    4. #define __initdata  __section(.init.data)  
    5. #define __initconst __section(.init.rodata)  
    6. #define __exitdata  __section(.exit.data)  
    7. #define __exit_call __used __section(.exitcall.exit)  

    ·首先需要简要说明一下GCC的驱动程序:


    #define __init __section(.init.text) __cold notrace
    __init用于标记函数,放在.init.text section,标记为初始化的函数,表明该函数供在初始化期间使用。在模块装载之后,模块装载就会将初始化函数扔掉。这样可以将该函数占用的内存释放出来。__initdata用于标记数据
    #define __cold   __attribute__((__cold__))
    __cold告诉编译器这个函数很可能不被执行到
    #define notrace __attribute__((no_instrument_function))
    notrace如同GCC的-finstrument-functions() 参数的作用是在程序中加入hook,让它在每次进入和退出函数的时候分别调用这个函数
    #define __used   __attribute__((__used__)) 意味着code必须发动附有该宏的函数
    __exit修饰词标记函数,只在模块卸载时使用。如果模块被直接编进内核则该函数就不会被调用。如果内核编译时没有包含该模块,则此标记的函数将被简单地丢弃。

    [cpp] view plaincopy
     
    1. #define __ref            __section(.ref.text) noinline  
    2. #define __refdata        __section(.ref.data)  
    3. #define __refconst       __section(.ref.rodata)  

    #define  noinline   __attribute__((noinline))  阻止该函数被内联

    [cpp] view plaincopy
     
    1. #define __exit          __section(.exit.text) __exitused __cold notrace  
    2.   
    3. /* Used for HOTPLUG */  
    4. #define __devinit        __section(.devinit.text) __cold notrace  
    5. #define __devinitdata    __section(.devinit.data)  
    6. #define __devinitconst   __section(.devinit.rodata)  
    7. #define __devexit        __section(.devexit.text) __exitused __cold notrace  
    8. #define __devexitdata    __section(.devexit.data)  
    9. #define __devexitconst   __section(.devexit.rodata)  
    10.   
    11. /* Used for HOTPLUG_CPU */  
    12. #define __cpuinit        __section(.cpuinit.text) __cold notrace  
    13. #define __cpuinitdata    __section(.cpuinit.data)  
    14. #define __cpuinitconst   __section(.cpuinit.rodata)  
    15. #define __cpuexit        __section(.cpuexit.text) __exitused __cold notrace  
    16. #define __cpuexitdata    __section(.cpuexit.data)  
    17. #define __cpuexitconst   __section(.cpuexit.rodata)  
    18.   
    19. /* Used for MEMORY_HOTPLUG */  
    20. #define __meminit        __section(.meminit.text) __cold notrace  
    21. #define __meminitdata    __section(.meminit.data)  
    22. #define __meminitconst   __section(.meminit.rodata)  
    23. #define __memexit        __section(.memexit.text) __exitused __cold notrace  
    24. #define __memexitdata    __section(.memexit.data)  
    25. #define __memexitconst   __section(.memexit.rodata)  

    2. 初始化宏

    [cpp] view plaincopy
     
    1. /* initcalls are now grouped by functionality into separate  
    2.  * subsections. Ordering inside the subsections is determined 
    3.  * by link order.  
    4.  * For backwards compatibility, initcall() puts the call in  
    5.  * the device init subsection. 
    6.  * 
    7.  * The `id' arg to __define_initcall() is needed so that multiple initcalls 
    8.  * can point at the same handler without causing duplicate-symbol build errors. 
    9.  */  
    10.   
    11. #define __define_initcall(level,fn,id)   
    12.     static initcall_t __initcall_##fn##id __used   
    13.     __attribute__((__section__(".initcall" level ".init"))) = fn  
    14.   
    15. /* 
    16.  * Early initcalls run before initializing SMP. 
    17.  * 
    18.  * Only for built-in code, not modules. 
    19.  */  
    20. #define early_initcall(fn)      __define_initcall("early",fn,early)  
    21.   
    22. /* 
    23.  * A "pure" initcall has no dependencies on anything else, and purely 
    24.  * initializes variables that couldn't be statically initialized. 
    25.  * 
    26.  * This only exists for built-in code, not for modules. 
    27.  */  
    28. #define pure_initcall(fn)       __define_initcall("0",fn,0)  
    29.   
    30. #define core_initcall(fn)       __define_initcall("1",fn,1)  
    31. #define core_initcall_sync(fn)      __define_initcall("1s",fn,1s)  
    32. #define postcore_initcall(fn)       __define_initcall("2",fn,2)  
    33. #define postcore_initcall_sync(fn)  __define_initcall("2s",fn,2s)  
    34. #define arch_initcall(fn)       __define_initcall("3",fn,3)  
    35. #define arch_initcall_sync(fn)      __define_initcall("3s",fn,3s)  
    36. #define subsys_initcall(fn)     __define_initcall("4",fn,4)  
    37. #define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)  
    38. #define fs_initcall(fn)         __define_initcall("5",fn,5)  
    39. #define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)  
    40. #define rootfs_initcall(fn)     __define_initcall("rootfs",fn,rootfs)  
    41. #define device_initcall(fn)     __define_initcall("6",fn,6)  
    42. #define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)  
    43. #define late_initcall(fn)       __define_initcall("7",fn,7)  
    44. #define late_initcall_sync(fn)      __define_initcall("7s",fn,7s)  
    45.   
    46. #define __initcall(fn) device_initcall(fn)  
    47.   
    48. #define __exitcall(fn)   
    49.     static exitcall_t __exitcall_##fn __exit_call = fn  
    50.   
    51. #define console_initcall(fn)   
    52.     static initcall_t __initcall_##fn   
    53.     __used __section(.con_initcall.init) = fn  
    54.   
    55. #define security_initcall(fn)   
    56.     static initcall_t __initcall_##fn   
    57.     __used __section(.security_initcall.init) = fn  

    首先,

    __define_initcall声明一个__initcall_##fn##id的initcall_t类型静态函数指针,并设置好属性,定义如下:
    typedef int (*initcall_t)(void);
    typedef void (*exitcall_t)(void);

    然后,初始化为fn,编译的时候就会放在__section__(".initcall" level ".init")里面

    3. .initcall.init section

    在include/asm-generic/vmlinux.lds.h中定义:

    [cpp] view plaincopy
     
    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)  
    21.   
    22. #define INIT_CALLS                            
    23.         VMLINUX_SYMBOL(__initcall_start) = .;             
    24.         INITCALLS                         
    25.         VMLINUX_SYMBOL(__initcall_end) = .;  
    26.   
    27. #define CON_INITCALL                              
    28.         VMLINUX_SYMBOL(__con_initcall_start) = .;         
    29.         *(.con_initcall.init)                     
    30.         VMLINUX_SYMBOL(__con_initcall_end) = .;  
    31.   
    32. #define SECURITY_INITCALL                         
    33.         VMLINUX_SYMBOL(__security_initcall_start) = .;        
    34.         *(.security_initcall.init)                
    35.         VMLINUX_SYMBOL(__security_initcall_end) = .;  

    在arm中section定义如下(arch/arm/kernel/vmlinux.lds.s):

    TCM是紧密耦合存储器,速度比 SDRAM 快很多,使得处理器能直接访问独立的指令和数据TCM(ITCM和DTCM)。TCM被用于存储实时性和性能要求极高的代码,它还提供一个DMA支持机制。不像AHP访问外部存储器,访问TCM是快速的,确定的,不造成总线负荷。

    [cpp] view plaincopy
     
    1.     .init : {           /* Init code and data       */  
    2.         _stext = .;  
    3.         _sinittext = .;  
    4.             HEAD_TEXT  
    5.             INIT_TEXT  
    6.             ARM_EXIT_KEEP(EXIT_TEXT)  
    7.         _einittext = .;  
    8.         ARM_CPU_DISCARD(PROC_INFO)  
    9.         __arch_info_begin = .;  
    10.             *(.arch.info.init)  
    11.         __arch_info_end = .;  
    12.         __tagtable_begin = .;  
    13.             *(.taglist.init)  
    14.         __tagtable_end = .;  
    15. #ifdef CONFIG_SMP_ON_UP  
    16.         __smpalt_begin = .;  
    17.             *(.alt.smp.init)  
    18.         __smpalt_end = .;  
    19. #endif  
    20.   
    21.         __pv_table_begin = .;  
    22.             *(.pv_table)  
    23.         __pv_table_end = .;  
    24.   
    25.         INIT_SETUP(16)  
    26.   
    27.         <span style="color:#ff0000;">INIT_CALLS  
    28. </span>     CON_INITCALL  
    29.         SECURITY_INITCALL  
    30.         INIT_RAM_FS  
    31.   
    32. #ifndef CONFIG_XIP_KERNEL  
    33.         __init_begin = _stext;  
    34.         INIT_DATA  
    35.         ARM_EXIT_KEEP(EXIT_DATA)  
    36. #endif  
    37.     }  

    #define INIT_CALLS       
      VMLINUX_SYMBOL(__initcall_start) = .;   
      INITCALLS      
      VMLINUX_SYMBOL(__initcall_end) = .;

    4. 初始化.initcallxx.init函数

    位于init/main.c

    [cpp] view plaincopy
     
    1. extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];  
    [cpp] view plaincopy
     
    1. static void __init do_pre_smp_initcalls(void)  
    2. {  
    3.     initcall_t *fn;  
    4.   
    5.     for (fn = <span style="color:#ff0000;">__initcall_start</span>; fn < <span style="color:#ff0000;">__early_initcall_end</span>; fn++)  
    6.         do_one_initcall(*fn);  
    7. }  
    [cpp] view plaincopy
     
    1. static void __init do_initcalls(void)  
    2. {  
    3.     initcall_t *fn;  
    4.   
    5.     for (fn = <span style="color:#ff0000;">__early_initcall_end</span>; fn < <span style="color:#ff0000;">__initcall_end</span>; fn++)  
    6.         do_one_initcall(*fn);  
    7. }  
    [cpp] view plaincopy
     
      1. int __init_or_module do_one_initcall(initcall_t fn)  
      2. {  
      3.     int count = preempt_count();  
      4.     int ret;  
      5.   
      6.     if (initcall_debug)  
      7.         ret = do_one_initcall_debug(fn);  
      8.     else  
      9.         <span style="color:#ff0000;">ret = fn();  
      10. </span>  
      11.     msgbuf[0] = 0;  
      12.   
      13.     if (ret && ret != -ENODEV && initcall_debug)  
      14.         sprintf(msgbuf, "error code %d ", ret);  
      15.   
      16.     if (preempt_count() != count) {  
      17.         strlcat(msgbuf, "preemption imbalance "sizeof(msgbuf));  
      18.         preempt_count() = count;  
      19.     }  
      20.     if (irqs_disabled()) {  
      21.         strlcat(msgbuf, "disabled interrupts "sizeof(msgbuf));  
      22.         local_irq_enable();  
      23.     }  
      24.     if (msgbuf[0]) {  
      25.         printk("initcall %pF returned with %s ", fn, msgbuf);  
      26.     }  
      27.   
      28.     return ret;  
      29. }  
  • 相关阅读:
    VS 2005中 讨厌的"异常助手"
    三步一计与一步三计
    S+S 的微软定义
    PMBOK2004版44个过程的工具和技术的总结
    如何在WCF中使用自定义的Header,(典型场景:业务系统的登陆与使用)
    SaaS模式探讨
    SQL 2005的row_number,(oracle 的 rownum)
    关于Django的登录系统
    CSRF Failed: Referer checking failed no Referer
    docker 入门笔记
  • 原文地址:https://www.cnblogs.com/pengdonglin137/p/3533861.html
Copyright © 2011-2022 走看看