subsys_initcall ,module_init,fs_initcall,arch_initcall等执行顺序

在init.h中找到定义

#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)
//module_init
#define __initcall(fn) device_initcall(fn)
查看
module_init 调用 __initcall 再 device_initcall

__define_initcall 定义:
#define __define_initcall(level,fn,id) \
	static initcall_t __initcall_##fn##id __used \
	__attribute__((__section__(".initcall" level ".init"))) = fn
所以 module_init 为
.initcall6.init
去头文件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) = .;

再看__early_initcall_end什么时候调用

在启动启动内核以后,初始化内核,启动第一个进程

kernel_init

static void __init do_initcalls(void)
{
	initcall_t *fn;
	for (fn = __early_initcall_end; fn < __initcall_end; fn++)
		do_one_initcall(*fn);
}
static void __init do_basic_setup(void)
{
......
	do_initcalls();
}
kernel_init(void * unused)
{
........
do_basic_setup();
}

所以会按照顺序调用这些init关键字修饰的fn,函数。

猜你喜欢

转载自blog.csdn.net/flyxiao28/article/details/80514408