initcall 宏閱讀筆記

linux4.14.39include/linux/module.h 中:linux

#define module_init(x)    __initcall(x);

#define module_exit(x)    __exitcall(x);

linux4.14.39/include/linux/init.h 中:數組

/* 
 * __initcall中指定的每個函數指針的名字都是不一樣的
 */
#define __initcall(fn) device_initcall(fn)

/*
 * 每個.c文件中只能定義一個 module_exit,由於所有module_exit定義
 * 的都是static的同名的函數指針:__exit_call = fn
 */
#define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn

linux4.14.39/include/linux/init.h 中:函數

#define pure_initcall(fn)        __define_initcall(fn, 0)
#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)

/* module_init()的等級是6 */
#define device_initcall(fn)        __define_initcall(fn, 6)
#define device_initcall_sync(fn)    __define_initcall(fn, 6s)

/* 觸摸板驅動中使用這個 late_initcall */
#define late_initcall(fn)        __define_initcall(fn, 7)
#define late_initcall_sync(fn)        __define_initcall(fn, 7s)

 

do_initcall_level() 函數只在 do_initcalls() 中被調用一次,也就是說這七個等級的 initcall 沒有任何一個等級作了特殊處理,同等對待,只是調用的前後次序不一樣而已。post

七個等級的 initcall 都被存放在 initcall_levels 這個數組中了,在 do_initcalls() 中一次性所有調用完。spa

linux4.14.39/init/main.c:命令行

static initcall_t *initcall_levels[] __initdata = {
    __initcall0_start,
    __initcall1_start,
    __initcall2_start,
    __initcall3_start,
    __initcall4_start,
    __initcall5_start,
    __initcall6_start,
    __initcall7_start,
    __initcall_end,
};
static void __init do_initcall_level(int level)
{
    initcall_t *fn;

    strcpy(initcall_command_line, saved_command_line);

    /*先解析命令行參數後再執行*/
    parse_args(initcall_level_names[level],
           initcall_command_line, __start___param,
           __stop___param - __start___param,
           level, level,
           NULL, &repair_env_string);

    for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
        do_one_initcall(*fn);
}

static void __init do_initcalls(void)
{
    int level;

    /*這決定了pure/arch/late_initcall()等的前後順序,越小越先被調用*/
    for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
        do_initcall_level(level);
}

 

總結指針

1. 一個.c文件中只能有一個 module_exit(對應的也就只能有一個 module_init)。
2. module_init 的 initcall level 爲6
3. 7個等級的 initcall 是一塊兒被處理的,只是調用的前後順序不一樣。code

相關文章
相關標籤/搜索