什么是Linux的initcall?
Linux的initcall是一种初始化调用的机制,它在Linux内核启动过程中用于执行一系列的初始化任务。initcall机制向Linux内核注册了多组回调函数,这些函数在系统初始化时按照预定的顺序被调用。initcall的主要目的是对设备、内核子系统等进行初始化,以确保系统能够正常运行。
在Linux内核中,initcall机制分为8个等级,从0到7。等级越低,优先级越高,执行顺序越早。其中,early、rootfs等特殊等级用于表示在不同阶段的初始化任务。内核提供了相应的宏来注册不同等级的initcall函数,这些宏位于include/linux/init.h文件中。
我们常见的module_init()、subsys_init()宏,都是负责把函数加入到initcall初始化列表中。
在哪里定义的这些宏?
定义的地方在 include/linux/init.h
/*
* Early initcalls run before initializing SMP.
*
* Only for built-in code, not modules.
*/
#define early_initcall(fn) __define_initcall(fn, early)
/*
* 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.
* Keep main.c:initcall_level_names[] in sync.
*/
#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)
#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(fn) device_initcall(fn)
#define __exitcall(fn) \
static exitcall_t __exitcall_##fn __exit_call = fn
#define console_initcall(fn) ___define_initcall(fn, con, .con_initcall)
怎么调用这些initcall的?
在Linux 6.1.9中,initcall是这样被调用的:
start_kernel()->arch_call_rest_init()->rest_init()---创建新的内核线程执行-->kernel_init()->kernel_init_freeable()->do_basic_setup()->do_initcalls()
接着在do_initcalls函数中,按照优先级,依次执行各个Level的initcall。同一个level内的执行顺序跟链接顺序有关。
转载请注明来源:https://longjin666.cn/?p=1804
欢迎关注我的公众号“灯珑”,让我们一起了解更多的事物~