一、macro fs_initcall,以fs_initcall(usb20_init)为例
1. fs_initcall(usb20_init) macro展开
*******************************************************************************
fs_initcall(usb20_init);
expanding:
fs_initcall(usb20_init) -->
static initcall_t __initcall_usb20_init5 __used \
__attribute__((__section__(".initcall" "5" ".init"))) = usb20_init;
*******************************************************************************
通过fs_initcall定义了一个initcall_t类型的函数指针变量,它指向usb20_init。
initcall_t函数指针类型定义:
*******************************************************************************
typedef int (*initcall_t)(void);
*******************************************************************************
2. kernel段定义
在include/asm-generic/vmlinux.lds.h中有如下macro定义:
*******************************************************************************
#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) \
*(.initcallbresume.init) \
*(.initcallresume.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) = .;
INIT_CALLS是在arch/arm/kernel/vmlinux.lds.S中被引用:
*******************************************************************************
__pv_table_begin = .;
*(.pv_table)
__pv_table_end = .;
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
SECURITY_INITCALL
*******************************************************************************
所以在step1中定义的initcall_t __initcall_usb20_init5指针变量放在initcall section中的.initcall5.init子段中。
3. step1中的__initcall_usb20_init5函数调用
在init/main.c中
*******************************************************************************
extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
static void __init do_initcalls(void)
{
initcall_t *fn;
for (fn = __early_initcall_end; fn < __initcall_end; fn++)
do_one_initcall(*fn);
}
*******************************************************************************
二、macro module_init
定义在include/linux/init.h头文件中:
*******************************************************************************
#define module_init(x) __initcall(x);
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn,6)
*******************************************************************************
__define_initcall定义一个initcall_t类型的__initcall_usb20_init6指针变量放在initcall section中的.initcall6.init子段中。
*******************************************************************************
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
*******************************************************************************
这个和上面的fs_initcall是类似的,fs_initcall是:
#define fs_initcall(fn) __define_initcall("5",fn,5)
所以fs_initcall和module_init定义的函数指针变量都放在kernel的initcall section,只是前者是位于initcall section中的.initcall5.init子段中,
而后者位于.initcall6.init子段中。存储在initcall section(这个段中的early子段除外)中的指针函数都会在kernel初始化时的do_initcalls函数中
被调用。5子段位于前面,所以它们先被执行,6后被执行。看include/linux/init.h中的宏定义就可以看出:
*******************************************************************************
#define early_initcall(fn) __define_initcall("early",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.
*/
#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)
#ifdef CONFIG_FAST_RESUME
#define beforeresume_initcall(fn) __define_initcall("bresume",fn,bresume)
#define resume_initcall(fn) __define_initcall("resume",fn,resume)
#endif
#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)
*******************************************************************************
1. fs_initcall(usb20_init) macro展开
*******************************************************************************
fs_initcall(usb20_init);
expanding:
fs_initcall(usb20_init) -->
static initcall_t __initcall_usb20_init5 __used \
__attribute__((__section__(".initcall" "5" ".init"))) = usb20_init;
*******************************************************************************
通过fs_initcall定义了一个initcall_t类型的函数指针变量,它指向usb20_init。
initcall_t函数指针类型定义:
*******************************************************************************
typedef int (*initcall_t)(void);
*******************************************************************************
2. kernel段定义
在include/asm-generic/vmlinux.lds.h中有如下macro定义:
*******************************************************************************
#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) \
*(.initcallbresume.init) \
*(.initcallresume.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) = .;
INIT_CALLS是在arch/arm/kernel/vmlinux.lds.S中被引用:
*******************************************************************************
__pv_table_begin = .;
*(.pv_table)
__pv_table_end = .;
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
SECURITY_INITCALL
*******************************************************************************
所以在step1中定义的initcall_t __initcall_usb20_init5指针变量放在initcall section中的.initcall5.init子段中。
3. step1中的__initcall_usb20_init5函数调用
在init/main.c中
*******************************************************************************
extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
static void __init do_initcalls(void)
{
initcall_t *fn;
for (fn = __early_initcall_end; fn < __initcall_end; fn++)
do_one_initcall(*fn);
}
*******************************************************************************
二、macro module_init
定义在include/linux/init.h头文件中:
*******************************************************************************
#define module_init(x) __initcall(x);
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn,6)
*******************************************************************************
__define_initcall定义一个initcall_t类型的__initcall_usb20_init6指针变量放在initcall section中的.initcall6.init子段中。
*******************************************************************************
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
*******************************************************************************
这个和上面的fs_initcall是类似的,fs_initcall是:
#define fs_initcall(fn) __define_initcall("5",fn,5)
所以fs_initcall和module_init定义的函数指针变量都放在kernel的initcall section,只是前者是位于initcall section中的.initcall5.init子段中,
而后者位于.initcall6.init子段中。存储在initcall section(这个段中的early子段除外)中的指针函数都会在kernel初始化时的do_initcalls函数中
被调用。5子段位于前面,所以它们先被执行,6后被执行。看include/linux/init.h中的宏定义就可以看出:
*******************************************************************************
#define early_initcall(fn) __define_initcall("early",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.
*/
#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)
#ifdef CONFIG_FAST_RESUME
#define beforeresume_initcall(fn) __define_initcall("bresume",fn,bresume)
#define resume_initcall(fn) __define_initcall("resume",fn,resume)
#endif
#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)
*******************************************************************************