1. 关于输出节Section
查看 /arch/i386/vmlinux.lds,其中有一段代码
__initcall_start = .;
.initcall.init : { *(.initcall.init) }
__initcall_end = .;
其含义是__initcall_start指向代码节.initcall.init的节首,而__initcall_end指向.i
nitcall.init的节尾。
使用 section 属性,可以让编译器将函数或变量放在指定的
节中。例如:
__initcall_start = .;
.initcall.init : { *(.initcall.init) }
__initcall_end = .;
其含义是__initcall_start指向代码节.initcall.init的节首,而__initcall_end指向.i
nitcall.init的节尾。
使用 section 属性,可以让编译器将函数或变量放在指定的
节中。例如:
++++
include
/
linux
/
init.h
78 : #define __init __attribute__ ((__section__ (".text.init")))
79 : #define __exit __attribute__ ((unused, __section__(".text.exit")))
80 : #define __initdata __attribute__ ((__section__ (".data.init")))
81 : #define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
82 : #define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
83 : #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
84 : #define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
78 : #define __init __attribute__ ((__section__ (".text.init")))
79 : #define __exit __attribute__ ((unused, __section__(".text.exit")))
80 : #define __initdata __attribute__ ((__section__ (".data.init")))
81 : #define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
82 : #define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
83 : #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
84 : #define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
do_initcalls所作的是系统中有关驱动部分的初始化工作,那么这些函数指针数据是怎样
放到了.initcall.init节呢?在include/linux/init.h文件中有如下3个定义:
1. #define __init_call __attribute__ ((unused,__section__ (".initcall.init
")))
__attribute__的含义就是构建一个在.initcall.init节的指向初始函数的指针。
2. #define __initcall(fn) static initcall_t __initcall_##fn __init_call = fn
##意思就是在可变参数使用宏定义的时候构建一个变量名称为所指向的函数的名称,并且
在前面加上__initcall_
3. #define module_init(x) __initcall(x);
很多驱动中都有类似module_init(usb_init)的代码,通过该宏定义逐层解释存放到.init
call.int节中。
待续