linux kernel initcall函数

在一个内核函数的定义中添加一个__init属性,在编译后的内核映像中位于特殊的init section中,但并不能保证会在内核初始化的时候被调用,应该通过以下的宏来确保初始化函数会被调用。


linux/init.h

     相关宏定义:

           /*
 * A "pure" initcall has no dependencies on anything else, and purely
 * initializes variables that couldn't be statically initialized.
 *
 * This only exists for built-in code, not for modules.
 */
#define pure_initcall(fn)               __define_initcall("0",fn,0)


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


#define module_init(fn)              __initcall(fn);

#define __initcall(fn)                    device_initcall(fn)         ---------> __define_initcall("6",fn,6)

  

   从上面可以看出,所有的宏都是建立在__define_initcall(level, fn, id)这个宏的基础之上:

 #define __define_intcall(level, fn, id)  \

        static intcall_t  __initcall_##fn##id__used \                   # typedef int(*initcall_t)(void);

       __attribute__((__section__(".initcall" level ".init"))) = fn

这句话的意思为定义一个initcall_t型的初始化函数,函数存放在.initcall”level”.init section内.

.initcall"level".init section定义在vmlinux.lds.h ?

#define INITCALLS                                                       \
        *(.initcallearly.init)                                          \
        VMLINUX_SYMBOL(__early_initcall_end) = .;                       \
        *(.initcall0.init)                                              \
        *(.initcall0s.init)                                             \
        *(.initcall1.init)                                              \
        *(.initcall1s.init)                                             \
        *(.initcall2.init)                                              \
        *(.initcall2s.init)                                             \
        *(.initcall3.init)                                              \
        *(.initcall3s.init)                                             \
        *(.initcall4.init)                                              \
        *(.initcall4s.init)                                             \
        *(.initcall5.init)                                              \
        *(.initcall5s.init)                                             \
        *(.initcallrootfs.init)                                         \
        *(.initcall6.init)                                              \
        *(.initcall6s.init)                                             \
        *(.initcall7.init)                                              \
        *(.initcall7s.init)


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

初始化流程:

start_kernel -> rest_init -> kernel_thread(kernel_init) #生成init内核线程

                                                 -> do_basic_setup -> do_initcalls

                                                                                             -->for (fn = __early_initcall_end; fn < __initcall_end; fn++)
                                                                                                         do_one_initcall(*fn);

依次循环调用预先存储在initcall section内的所有各个级别的初始化函数。

                                                                                                                   



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值