您的位置:首页 > 运维架构 > Linux

linux kernel initcall函数

2012-05-03 10:16 323 查看
在一个内核函数的定义中添加一个__init属性,在编译后的内核映像中位于特殊的init section中,但并不能保证会在内核初始化的时候被调用,应该通过以下的宏来确保初始化函数会被调用。

linux/init.h

相关宏定义:

/*

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

#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)

#define module_init(fn) __initcall(fn);

#define __initcall(fn) device_initcall(fn) ---------> __define_initcall("6",fn,6)

从上面可以看出,所有的宏都是建立在__define_initcall(level, fn, id)这个宏的基础之上:

#define __define_intcall(level, fn, id) \

static intcall_t __initcall_##fn##id__used \ # typedef int(*initcall_t)(void);

__attribute__((__section__(".initcall" level ".init"))) = fn

这句话的意思为定义一个initcall_t型的初始化函数,函数存放在.initcall”level”.init section内.

.initcall"level".init section定义在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) = .;

初始化流程:

start_kernel -> rest_init -> kernel_thread(kernel_init) #生成init内核线程

-> do_basic_setup -> do_initcalls

-->for (fn = __early_initcall_end; fn < __initcall_end; fn++)

do_one_initcall(*fn);

依次循环调用预先存储在initcall section内的所有各个级别的初始化函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: