在linux内核中,我们经常会使用到一些宏定义,比如:

__init
__initdata
__exitdata

等等。那么这些宏定义到底什么意思呢?接下来我们就来看一下。

kernel/include/linux/init.h

我们来选择一些常用的宏定义,如下所示:

/* These are for everybody (although not all archs will actually
   discard it in modules) */
#define __init      __section(.init.text) __cold notrace
#define __initdata  __section(.init.data)
#define __initconst __constsection(.init.rodata)
#define __exitdata  __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)


#define __exit          __section(.exit.text) __exitused __cold notrace

/* For assembly routines */
#define __HEAD      .section    ".head.text","ax"
#define __INIT      .section    ".init.text","ax"
#define __FINIT     .previous

#define __INITDATA  .section    ".init.data","aw",%progbits
#define __INITRODATA    .section    ".init.rodata","a",%progbits
#define __FINITDATA .previous

#define __CPUINIT        .section   ".cpuinit.text", "ax"
#define __CPUINITDATA    .section   ".cpuinit.data", "aw"
#define __CPUINITRODATA  .section   ".cpuinit.rodata", "a"

#define __MEMINIT        .section   ".meminit.text", "ax"
#define __MEMINITDATA    .section   ".meminit.data", "aw"
#define __MEMINITRODATA  .section   ".meminit.rodata", "a"

/* silence warnings when references are OK */
#define __REF            .section       ".ref.text", "ax"
#define __REFDATA        .section       ".ref.data", "aw"
#define __REFCONST       .section       ".ref.rodata", "a"

我们可以看到大多是和section相关的定义,这个段定义什么作用呢,它是为了告诉链接器应该把这个函数或者数据放置在哪个位置。一般是指放置到内核镜像的哪个位置上。内核相当于一个非常大的可执行程序,它里面包含了好多内容,我们按照分段的原则来存放这些内容。具体段的存放规则是由vmlinux.lds文件定义,它是负责把段信息告诉链接器的,当然我们也要在代码中声明属于哪个段。
通常编译器将函数放在.text 节,变量放在.data 或 .bss 节,使用 section 属性,可以让编译器将函数或变量放在指定的节中。那么例如:前面对init 的定义便表示将它修饰的代码放在.init.text节。内核把段分的非常细致,是因为它会在运行过程中去定位相应的数据和代码,这样将更加方便处理。就像init 修饰的所有代码都放在.init.text段,它只在启动阶段会被内核调用到,当初始化结束后就会释放这部分内存,以便充分利用内存,这个就是属于内存管理的部分了。

C代码中一般是按照这种规则来传递段信息的

__attribute__((section("section_name"))) 

可是上面的定义并不是如此,其实__section也是一个宏定义,我们在kernel/include/linux/compiler.h:

#ifndef __section
# define __section(S) __attribute__ ((__section__(#S)))
#endif

至于汇编代码我们就都很清楚了,直接使用.section即可。


作者:程序猿Ricky
https://blog.csdn.net/rikeyone/article/details/51545999