Linux源码__init宏
阅读数:118 评论数:0
跳转到新版页面分类
Linux
正文
一、概述
在 Linux 内核开发中,__init
宏是一个特殊的宏,用于标记某些函数或数据是初始化代码或数据。当内核启动并完成初始化后,这部分被标记为 __init
的代码和数据可以被丢弃,以节省内存。这对于嵌入式系统或资源有限的环境特别有用,因为它允许系统在不再需要初始化代码后释放出这部分内存供其他用途使用。
二、源码相关
在内核里经常可以看到__init, __devinit这样的语句,这都是在init.h中定义的宏, gcc在编译时会把被修饰的内容放到这些宏所代表的section中。
#define __init __section(.init.text) __cold __latent_entropy __noinitretpoline
#define __initdata __section(.init.data)
#define __initconst __section(.init.rodata)
#define __exitdata __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)
#define __section(section) __attribute__((__section__(section)))
__section(.init.text)指放到.init.text的数据段中。这样系统在初始化,只需要把.init.text数据段中所有初始化执行一遍即可,当系统启动完毕后,这个段中的内存就会被释放供其它使用。
#define __cold __attribute__((__cold__))
__cold标识该函数针对大小而不是速度进行优化。
【include/linux/complier-gcc.h】
#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
#define __latent_entropy __attribute__((latent_entropy))
#endif
__latent_entropy用于函数,那么plugin将对其进行检测,用于变量,那么plugin将用一个随机值初始化它。
【include/linux/complier-gcc.h】
#ifdef CONFIG_RETPOLINE
#define __noretpoline __attribute__((__indirect_branch__("keep")))
#endif
/* Built-in __init functions needn't be compiled with retpoline */
#if defined(__noretpoline) && !defined(MODULE)
#define __noinitretpoline __noretpoline
#else
#define __noinitretpoline /一般情况下,定义了MODULE,就会走这个分支**/
#endif
其典型用法如下:
static int __init xxx_drv_init(void)
{
return pci_register_driver(&xxx_driver);
}
1、一部分内核初始化机制依赖它。
如kernel将初始化要执行的init函数,分为7个级别,core_initcall, postcore_initcall, arch_initcall, subsys_initcall, fs_initcall, device_initcall, late_initcall。这7个级别优行列级递减,即先执行core_initcall,最后执行late_initcall。通过使用文中提到的宏, gcc会将初始化代码按下面结构安排。
在内核初始化时,从__initcall_start到__initcall_end之间的initcall被执行一次。
2、提高系统效率
初始化代码的特点是:在系统启动时运行,且一旦运行马上退出内存,不再占用内存。