about macros fs_initcall and module_init

本文详细介绍了Linux内核中的fs_initcall和module_init宏的使用和工作原理。fs_initcall用于将函数放置在.initcall5.init子段,而module_init则将函数放在.initcall6.init子段。两者都是在内核初始化阶段由do_initcalls函数按顺序调用,fs_initcall的函数先执行。内核初始化过程中,根据不同的宏定义,将函数组织在不同优先级的子段中,以控制执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、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)
*******************************************************************************





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值