zoukankan      html  css  js  c++  java
  • 内核中 subsys_initcall 以及初始化标号

    今天在看内核中无线的实现时,发现一个调用 subsys_initcall(cfg80211_init);搜索一些资料:

    subsys_initcall 的定义在 include/linux/init.h 中,定义如下:

    #define core_initcall(fn)       __define_initcall(fn, 1)
    #define core_initcall_sync(fn)    __define_initcall(fn, 1s)
    #define postcore_initcall(fn)        __define_initcall(fn, 2)
    #define postcore_initcall_sync(fn) __define_initcall(fn, 2s)
    #define arch_initcall(fn)       __define_initcall(fn, 3)
    #define arch_initcall_sync(fn)      __define_initcall(fn, 3s)
    #define subsys_initcall(fn)     __define_initcall(fn, 4)
    #define subsys_initcall_sync(fn)  __define_initcall(fn, 4s)
    #define fs_initcall(fn)         __define_initcall(fn, 5)
    #define fs_initcall_sync(fn)        __define_initcall(fn, 5s)
    #define rootfs_initcall(fn)          __define_initcall(fn, rootfs)
    #define device_initcall(fn)          __define_initcall(fn, 6)
    #define device_initcall_sync(fn)  __define_initcall(fn, 6s)
    #define late_initcall(fn)             __define_initcall(fn, 7)
    #define late_initcall_sync(fn)     __define_initcall(fn, 7s)

    查看宏定义 _define_initcall 定义在同一个文件中(include/linux/init.h)

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

    定义了一个函数指针赋值的实现,    __initcall_##fn##id  函数的实现为  fn函数;编译的时候需要把这个函数指针变量放置到名称为 ".initcall" level ".init"的section中。

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

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

    #define INIT_CALLS       
      VMLINUX_SYMBOL(__initcall_start) = .;   
      *(.initcallearly.init)     
      INIT_CALLS_LEVEL(0)     
      INIT_CALLS_LEVEL(1)     
      INIT_CALLS_LEVEL(2)     
      INIT_CALLS_LEVEL(3)     
      INIT_CALLS_LEVEL(4)     
      INIT_CALLS_LEVEL(5)     
      INIT_CALLS_LEVEL(rootfs)    
      INIT_CALLS_LEVEL(6)     
      INIT_CALLS_LEVEL(7)     
      VMLINUX_SYMBOL(__initcall_end) = .;

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

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

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

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

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

    参考文档  :  http://blog.csdn.net/thl789/article/details/6581146#

  • 相关阅读:
    excelhelp
    导入数据到GridView
    sql2005悠改sa
    状态存储管理 encode,decode,transfer
    Session持久化
    Microsoft SQL Server 2005 数据类型
    Cookie (HttpCookie的实例)
    role设计
    ajax
    poj 3370 Halloween treats 夜
  • 原文地址:https://www.cnblogs.com/rohens-hbg/p/6524231.html
Copyright © 2011-2022 走看看