linux內核中的subsys_initcall是干什么的?


注意:使用的內核源碼版本為5.1.3

1. subsys_initcall長什么樣子?

  它其實是個宏定義,定義如下:

    #define subsys_initcall(fn)     __define_initcall(fn, 4) (注意,這是使用在內置模塊中的)

    或

     #define subsys_initcall(fn)     module_init(fn) (注意,這是使用在可加載模塊中的)

2. 進一步解剖__define_initcall

 #define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)

3. 再解剖___define_initcall

#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
#define ___define_initcall(fn, id, __sec)           \
    __ADDRESSABLE(fn)                   \
    asm(".section   \"" #__sec ".init\", \"a\"  \n" \
    "__initcall_" #fn #id ":            \n" \
        ".long  " #fn " - .         \n" \
        ".previous                  \n");
#else
#define ___define_initcall(fn, id, __sec) \
    static initcall_t __initcall_##fn##id __used \
        __attribute__((__section__(#__sec ".init"))) = fn;
#endif

4. 結合以上內容可知

 如果未定義宏CONFIG_HAVE_ARCH_PREL32_RELOCATIONS,那么subsys_initcall就被展開為:

  static initcall_t __initcall_fn4 __used \

    __attribute__((__section_(.initcall4.init))) = fn

  也就是將fn鏈接到段.initcall4.init中

 

5. subsys_initcall與module_init有何聯系?

 5.1 先看看module_init是什么吧?

/* Each module must use one module_init(). */ (在編譯為可加載模塊時使用這個定義)
#define module_init(initfn)                 \
    static inline initcall_t __maybe_unused __inittest(void)        \
    { return initfn; }                  \
    int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));

 

   或  

define module_init(x)  __initcall(x); (在編譯為內置模塊時使用這個定義)

 

 5.2 __initcall的定義是怎樣的呢?

#define __initcall(fn) device_initcall(fn)

 5.3 device_initcall是怎樣的呢?

#define device_initcall(fn)     __define_initcall(fn, 6)

 

  

 5.4 結論

  從以上分析可以看出:

    在編譯某驅動為內置代碼時,subsys_initcall與module_init僅僅是__define_initcall的第二個參數不同而已,前者使用4,后者使用6,因此歸納出僅僅是誰先被執行的差異,subsys_initcall比module_init先執行

 

 

  

    

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM