内核中的宏定义__init,__initdata,__exitdata
2016-05-31 15:15
585 查看
在linux内核中,我们经常会使用到一些宏定义,比如__init,__initdata,__exitdata等等。那么这些宏定义到底什么意思呢?接下来我们就来看一下。
kernel/include/linux/init.h:
我们来选择一些常用的宏定义,如下所示:
我们可以看到大多是和section相关的定义,这个段定义什么作用呢,它是为了告诉链接器应该把这个函数或者数据放置在哪个位置。一般是指放置到内核镜像的哪个位置上。内核相当于一个非常大的可执行程序,它里面包含了好多内容,我们按照分段的原则来存放这些内容。具体段的存放规则是由vmlinux.lds文件定义,它是负责把段信息告诉链接器的,当然我们也要在代码中声明属于哪个段。
通常编译器将函数放在.text 节,变量放在.data 或 .bss 节,使用 section 属性,可以让编译器将函数或变量放在指定的节中。那么例如:前面对__init 的定义便表示将它修饰的代码放在.init.text节。内核把段分的非常细致,是因为它会在运行过程中去定位相应的数据和代码,这样将更加方便处理。就像__init 修饰的所有代码都放在.init.text段,它只在启动阶段会被内核调用到,当初始化结束后就会释放这部分内存,以便充分利用内存,这个就是属于内存管理的部分了。
C代码中一般是按照这种规则来传递段信息的
可是上面的定义并不是如此,其实__section也是一个宏定义,我们在kernel/include/linux/compiler.h:
至于汇编代码我们就都很清楚了,直接使用.section即可。
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即可。
相关文章推荐
- Linux 自检和 SystemTap
- LKRG:用于运行时完整性检查的可加载内核模块
- 一张图看尽 Linux 内核运行原理
- Greg Kroah-Hartman 解释内核社区是如何使 Linux 安全的
- Linux内核链表实现过程
- PHP内核探索之解释器的执行过程
- 深入理解PHP内核(二)之SAPI探究
- C++中Semaphore内核对象用法实例
- 一张图看尽Linux内核运行原理
- 深入理解PHP内核(一)
- PHP内核探索之变量
- 深入php内核之php in array
- 浅谈Linux内核创建新进程的全过程
- 修改内核 内存分配 root、文件系统和内核镜像的位置
- 移植linux-2.6.30.4到S3C2440
- 看《Linux0.11内核完全注释2.01》的方法
- 升级LINUX内核(支持8G内存)的命令
- FreeBSD系统优化部分内核参数调整中文注释
- Linux2.6X内核中文件相关结构体总结
- 内核的主要配置文件的详细说明