__init、__initdata和__exit、__exitdata的定义位于<kernel/include/linux/init.h>
1 /* These are for everybody (although not all archs will actually 2 discard it in modules) */ 3 #define __init __section(.init.text) __cold notrace 4 #define __initdata __section(.init.data) 5 #define __initconst __constsection(.init.rodata) 6 #define __exitdata __section(.exit.data) 7 #define __exit_call __used __section(.exitcall.exit) 8 9 10 #define __exit __section(.exit.text) __exitused __cold notrace 11 12 /* For assembly routines */ 13 #define __HEAD .section ".head.text","ax" 14 #define __INIT .section ".init.text","ax" 15 #define __FINIT .previous 16 17 #define __INITDATA .section ".init.data","aw",%progbits 18 #define __INITRODATA .section ".init.rodata","a",%progbits 19 #define __FINITDATA .previous 20 21 #define __CPUINIT .section ".cpuinit.text", "ax" 22 #define __CPUINITDATA .section ".cpuinit.data", "aw" 23 #define __CPUINITRODATA .section ".cpuinit.rodata", "a" 24 25 #define __MEMINIT .section ".meminit.text", "ax" 26 #define __MEMINITDATA .section ".meminit.data", "aw" 27 #define __MEMINITRODATA .section ".meminit.rodata", "a" 28 29 /* silence warnings when references are OK */ 30 #define __REF .section ".ref.text", "ax" 31 #define __REFDATA .section ".ref.data", "aw" 32 #define __REFCONST .section ".ref.rodata", "a"
这些宏大多跟和section相关的定义
这些宏定义的作用是告诉编译器将这些函数或者数据放入相应的section中,一般是指放置到内核镜像的哪个位置上。内核中的内容按照分段的原则来存放。具体段的存放规则是由vmlinux.lds文件定义,它是负责把段信息告诉链接器的,当然我们也要在代码中声明属于哪个段。
通常编译器将函数放在.text 节,变量放在.data 或 .bss 节,使用 section 属性,可以让编译器将函数或变量放在指定的节中。
在模块加载的阶段,.ko文件中的代码和数据的加载区域是根据section来加载的。
比如:如果函数的定义中带有__init,那么这个函数的所有代码会被放入.init.text的section中。
如果函数的定义中带有__initdata,那么这个函数的所有代码会被放入.init.data的section中。
之所以要使用这个宏定义,其中一个原因是标记为初始化的函数和数据,表明该函数和数据仅在初始化期间使用。在模块装载之后,模块装载就会将初始化函数扔掉。这样可以将该函数占用的内存释放出来。
详见: