浅尝辄止37-module init1

书接浅尝辄止36-module init0
我们知道module_init(x)的结果是static initcall_t __initcall_x6 = x;,并且这个变量是放在.initcall6.init

initcall6.init是什么?

initcall6.init不是显式定义的,所以不能从代码中直接grep到它。这是内核的代码最麻烦的点之一,很多宏是非显式定义的,再厉害的代码工具也不能帮助你直接找到一些宏的定义,这段代码也就成了天书。
对于这种非显式定义的宏,也不是完全没有办法,我的经验是把它拆开程单独的词,再去搜索那些词,就可能找到了。
例如在kernel/include/asm-generic/vmlinux.lds.h中有如下定义

#define INIT_CALLS_LEVEL(level)                     \
        VMLINUX_SYMBOL(__initcall##level##_start) = .;      \
        *(.initcall##level##.init)              \
        *(.initcall##level##s.init)             \

INIT_CALLS_LEVEL(6)展开就是

        VMLINUX_SYMBOL(__initcall6_start) = .;      \
        *(.initcall6.init)              \
        *(.initcall6s.init)             \

至少.initcall6.init出现了。就在这个define的下面,还有

#define INIT_CALLS                          \
        VMLINUX_SYMBOL(__initcall_start) = .;           \
        *(.initcallearly.init)                  \
        INIT_CALLS_LEVEL(0)                 \
        INIT_CALLS_LEVEL(1)                 \
        INIT_CALLS_LEVEL(2)                 \
        INIT_CALLS_LEVEL(3)                 \
        INIT_CALLS_LEVEL(4)                 \
        INIT_CALLS_LEVEL(5)                 \
        INIT_CALLS_LEVEL(rootfs)                \
        INIT_CALLS_LEVEL(6)                 \
        INIT_CALLS_LEVEL(7)                 \
        VMLINUX_SYMBOL(__initcall_end) = .;

VMLINUX_SYMBOL

关于VMLINUX_SYMBOL,我们就按照下面最简单的版本理解好了。

#define __VMLINUX_SYMBOL(x) x
#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)

*(.initcall6.init)

*(.initcall6.init)这个写法在比较新的版本中会写成KEEP(*(.initcall6.init)),意思是告诉编译器将局部符号包含在目标文件的符号表中,我理解是__initcall6_start.initcall6.init等价。

且听下回分解……

你可能感兴趣的:(浅尝辄止37-module init1)