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

本文聚焦Linux内核源码,解析了__visible宏定义。介绍了__attribute__关键字,它是编译器指令,可设置函数、变量和类型属性。还阐述了__externally_visible__含义,以及__attribute__((__externally_visible__))和__attribute__((visibility(\default\)))的定义,说明了GCC的visibility属性特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

__visible宏定义

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

asmlinkage __visible void __init __no_sanitize_address start_kernel(void)

那么,它的作用是什么?
先去找下宏定义(估计又是和编译器相关,而且会分不同架构去定义):

【include/linux/complier_attributes.h】
/* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute */
#if __has_attribute(__externally_visible__)
# define __visible                      __attribute__((__externally_visible__))
#else
# define __visible
#endif

【scripts/gcc_plugins/gcc-common.h】
#ifndef __visible
#define __visible __attribute__((visibility("default")))
#endif

__attribute__关键字定义:

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

__attribute__的作用:

GNU C 的一大特色就是__attribute__ 机制。
__attribute 其实是个编译器指令,告诉编译器声明的特性,或者让编译器进行更多的错误检查和高级优化。

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

__externally_visible__的含义:

externally_visible的左右的下划线是可以去掉的,主要是为了防止重名的宏定义。

在使用__attribute__ 参数时,你也可以在参数的前后都加上“__”(两个下划线),例如,使用__aligned__而不是aligned,这样,你就可以在相应的头文件里使用它而不用关心头文件里是否有重名的宏定义。

externally_visible的含义:
附加到全局变量或函数的该属性使 -整个程序命令行选项,因此该对象在当前编译单元外部仍然可见。
如果 -整个程序 与 -flto和 gold被用作连接体插件, externally_visible属性被自动地添加到功能。对于其他无法生成解析文件的链接器,externally_visible仍然需要显式属性。
externally_visible的作用就是使该对象在当前编译单元外部仍然可见。

__attribute__((__externally_visible__))定义:

在C ++中,可以用visible属性标记类的成员函数和静态成员变量。如果知道仅应从一个共享库中使用特定方法或静态成员变量,这将很有用。
可以将其标记为隐藏,而该类的其余部分具有默认可见性。必须注意避免违反“一个定义”规则;例如,将内联方法标记为隐藏而不将整个类标记为隐藏通常是没有用的。

这里__attribute__((externally_visible))的定义是说明,被标记的函数或变量在当前编译单元外部仍然可见。

在别的文件中,可以直接调用该函数或变量。如果没有使用__attribute__((externally_visible))去标记,在外部调用会提示找不到对应的函数(因为默认编译时函数是被隐藏的),效果可能和内核中EXPORT_SYMBOL有点类似吧。

__attribute__((visibility("default")))定义:

默认可见性是对象文件格式的正常情况。此值可用于可见性属性,以覆盖可能更改实体假定的可见性的其他选项。

在ELF上,默认可见性意味着声明对其他模块可见,而在共享库中,意味着声明的实体可以被覆盖。
在Darwin上,默认可见性意味着该声明对其他模块可见。

默认可见性对应于该语言中的“外部链接”。

visibility ("visibility_type")定义

此属性影响其所附声明的链接。它可以应用于变量(请参阅“通用变量属性”)和类型(请参见“通用类型属性”)以及函数。 visibility 支持四个可见性类型值:默认,隐藏,受保护或内部可见性。

GCC 有个visibility属性, 该属性是说, 启用这个属性:

  1. 当-fvisibility=hidden时 动态库中的函数默认是被隐藏的即 hidden. 除非显示声明为__attribute__((visibility(“default”))).
  2. 当-fvisibility=default时 动态库中的函数默认是可见的.除非显示声明为__attribute__((visibility(“hidden”))).

Ps:特别说明: 这个特性是 GCC4.0 以后才有的.


参考:
https://blog.csdn.net/veryitman/article/details/46756683
gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Evan_ZGYF丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值