【GCC系列】深入理解Linux内核 -- __init宏定义

本文使用的Linux源码内核版本:Linux 5.10.0

__init宏定义

在Linux的内核源码里,尤其是一些关键的内核函数,会包含__init宏,它是用来做什么的呢?

asmlinkage __visible void __init __no_sanitize_address start_kernel(void)

那么,它的作用是什么?先去找下宏定义:

【include/linux/init.h】
#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")

可以看到__init宏由多个关键字组成:__section、__cold 、__latent_entropy 、__noinitretpoline。
下面单独先对这几个关键字进行分析。

__section(".init.text")的含义

__section就是GCC的一个编译特性,在编译时该带该关键字的函数,放到“.init.text”的数据段中。
这样做的目的就是将相关的函数全部放在一起,比如这里将相关的初始化时需要运行的函数全部放到".init.text"数据段,在系统运行时直接让PC指针按顺序执行这些函数。

__section关键字:

__section实际也是一个宏,它的定义如下:

#define __section(section)              __attribute__((__section__(section)))

又看到了熟悉的__attribute__关键字,

__attribute__的作用:

GNU C 的一大特色就是__attribute__ 机制。

__attribute 其实是个编译器指令,告诉编译器声明的特性,或者让编译器进行更多的错误检查和高级优化。

attribute 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。
attribute 书写特征是:attribute 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__ 参数。
attribute 语法格式为:attribute ((attribute-list)) 在使用__attribute__ 参数时,你也可以在参数的前后都加上“__” (两个下划线),例如,使用__aligned__而不是aligned
,这样,你就可以在相应的头文件里使用它而不用关心头文件里是否有重名的宏定义。

GCC中有定义

section (“section-name”)
Normally, the compiler places the code it generates in the text section. Sometimes, however, you need additional sections, or you need certain particular functions to appear in special sections. The section attribute specifies that a function lives in a particular section. For example, the declaration:
extern void foobar (void) attribute ((section (“bar”)));
puts the function foobar in the bar section.
Some file formats do not support arbitrary sections so the section attribute is not available on all platforms. If you need to map the entire contents of a module to a particular section, consider using the facilities of the linker instead.

通常,编译器会将其生成的代码放在该text部分中。但是,有时您需要其他部分,或者需要某些特殊功能才能出现在特殊部分中。该section 属性指定函数位于特定节中。
针对该定义,我们继续分析。

__attribute__((__section__(section)))定义:

attribute((section(”name“)))是gcc编译器支持的一个编译特性,实现在编译时把某个函数/数据放到name的数据段中。

这样做的优点:

  1. 系统在初始化时,不需要知道有什么模块需要初始化,只需要把name数据段中的所有初始化接口执行一遍即可。
  2. 当系统启动完毕后,这个段中的内存会被释放掉供其他使用。

__cold宏定义:

__cold也是一个宏,它的定义如下:

/*
 *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-cold-function-attribute
 *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-cold-label-attribute
 */
#define __cold                          __attribute__((__cold__))

熟悉的__attribute__关键字,参考上文。

__cold__的属性用于通知编译器该函数不太可能执行。

该函数针对大小而不是速度进行了优化,并且在许多目标上将其放置在文本部分的特殊子节中,因此所有冷函数都显示在一起,从而提高了程序非冷部分的代码局部性。
分支预测机制将导致代码中调用冷函数的路径标记为不太可能。因此,标记用于处理不太可能的条件(例如perror寒冷)的函数很有用,以改善在极少数情况下确实会调用标记函数的热函数的优化。

__latent_entropy宏定义:

__latent_entropy也是一个宏,它的定义如下:

【include/linux/complier-gcc.h】
#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
#define __latent_entropy __attribute__((latent_entropy))
#endif

latent_entropy是gcc编译器支持的一个编译特性,它只能作用于函数和变量。
如果它是在一个函数上,那么plugin将对其进行检测。
如果属性在一个变量上,那么plugin将用一个随机值初始化它。变量必须是整型、整型数组类型或具有整型字段的结构。

__noinitretpoline宏定义:

__noinitretpoline也是一个宏,它的定义如下:

【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

间接分支。用于预测间接分支指令的目标地址的方法和间接分支预测器逻辑单元。
在表中存储间接分支指令的预测的目标地址,所述预测的目标地址是由之前的间接分支指令的间接路径历史与之前的条件分支指令的被采用/不被采用历史的组合进行索引的。
不过一般情况下,定义了MODULE,就会走下面的分支。(这个宏一般用不到)


参考:
https://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA==&mid=2652663356&idx=1&sn=779762953029c0e0946c22ef2bb0b754&chksm=810f28a1b678a1b747520ba3ee47c9ed2e8ccb89ac27075e2d069237c13974aa43537bff4fba&mpshare=1&scene=1&srcid=0111Ys4k5rkBto22dLokVT5A&pass_ticket=bGNWMdGEbb0307Tm%2Ba%2FzAKZjWKsImCYqUlDUYPZYkLgU061qPsHFESXlJj%2Fyx3VM#rd

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Evan_ZGYF丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值