宏DATA_SET()展开成MAKE_SET(),宏MAKE_SET()指向所有隐含的
sysinit幻数:/usr/include/linker_set.h
#define MAKE_SET(set, sym)
static void const * const __set_##set##_sym_##sym = &sym;
__asm(".section .set." #set ","aw"");
__asm(".long " #sym);
__asm(".previous")
#endif
#define TEXT_SET(set, sym) MAKE_SET(set, sym)
#define DATA_SET(set, sym) MAKE_SET(set, sym)
回到我们的例子中,经过宏的展开过程,将会产生如下声明:
static struct sysinit announce_sys_init = {
SI_SUB_COPYRIGHT,
SI_ORDER_FIRST,
(sysinit_cfunc_t)(sysinit_nfunc_t) print_CADdr_t,
(void *) copyright
};
static void const *const __set_sysinit_set_sym_announce_sys_init =
&announce_sys_init;
__asm(".section .set.sysinit_set" ","aw"");
__asm(".long " "announce_sys_init");
__asm(".previous");
第一个__asm指令在内核可执行文件中建立一个ELF节(section)。这发生在内核链接的时候。
这一节将被命令为.set.sysinit_set。这一节的内容是一个32位值——announce_sys_init结构的地址,这个结构正是第二个__asm指令所定义的。第三个__asm指令标记节的结束。
如果前面有名字相同的节定义语句,节的内容(那个32位值)将被填加到已存在的节里,这样就构造出了一个32位指针数组。用objdump察看一个内核二进制文件,也许你会注意到里面有这么几个小的节:% objdump -h /kernel
标签: