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