8

我已经浏览了使用 _ 属性_((section("name")) 的代码。我知道对于 gcc 编译器,这允许您告诉链接器将创建的对象放在特定部分“name”(带有“name”链接器文件中声明的绝对地址)。

这样做而不是仅使用 .data 部分有什么意义?

4

3 回答 3

8

有许多可能的用途。[编辑添加注释:这只是我自己看到或考虑过的使用示例,不是完整列表。]

例如,Linux 内核将一些代码和数据部分标记为仅在内核引导期间使用。这些可以在内核运行后丢弃,回收空间用于其他用途。

您可以使用它来标记需要在特定处理器变体上修补的代码或数据值,例如,有或没有协处理器。

您可以使用它来使事物存在于“特殊”地址空间中,这些地址空间将被烧录到 PROM 或保存在 EEPROM 中,而不是普通内存中。

您可以使用它来收集代码或数据区域以用于初始化和清理等目的,例如在程序启动之前和结束时运行的 C++ 构造函数和析构函数,或者用于使用较短的寻址模式(我不知道有多少)将适用于 ARM,因为我自己没有编写任何 ARM 代码)。

实际使用取决于链接描述文件。

于 2013-08-21T01:48:45.547 回答
3

从用例的角度来看,有很多不同类型的.data,例如:

  • 特定 CPU 和/或 NUMA 节点的本地数据
  • 上下文之间共享的数据(如用户/内核空间,.vdsovsyscall页面。或者,另一个示例,引导加载程序和内核)
  • 只读数据或具有特定访问模式/类型限制的其他数据(例如,可缓存性或缓存驻留 - 后者可以在某些 ARM SoC 上指定)
  • 持续“状态转换”的数据(例如休眠图像加载,或崩溃内核/快速重启重新初始化)
  • 具有特定生命周期/生命周期的数据(仅在引导或操作期间的特定阶段使用,一次写入数据)
  • 特定于特定内核子系统或特定内核模块的数据
  • “代码并置”数据(x64 中的寻址偏移量为正/负 2GB,因此如果您想要RIP-relative 寻址,数据必须在当前执行代码的范围内)
  • 映射到某些特定硬件寄存器空间的数据 VA 范围

所以最后它通常是关于属性的(这里使用的这个词比__attribute__(...)允许你从 gcc 源代码中陈述的更通用。另一个部分是否需要和/或有用是......在旁观者的眼中 -系统设计师,即。

因此,该section属性的可用性允许灵活性,也就是说,恕我直言,这是一件好事。

于 2013-08-22T12:36:09.237 回答
0

多年后,我将添加一个具体的细节,因为它值得写下来。

如果您创建自己的部分,您可以自己管理它。特别是,您可以使用预处理器宏将某些数据项插入您的特殊部分。如果唯一使用该特殊部分的是您的预处理器宏,那么您就有能力以分布式方式创建数据结构。

这是什么意思?这意味着您可以编写一个预处理器宏,例如ADD_VAR_TO_SPECIAL_SECTION(...)并将一堆不同的值以随机顺序连接到您的部分中相当于一个数组(或者只是一个大的旧堆,如果它们不是完全相同的类型)。

这使您能够在编译时创建(随机排序的)数据数组。没有初始化,没有注册,没有开销。您只需编译和链接您的代码,所有不同源文件中的所有宏都将它们的所有值添加到一个大数组中。

你怎么能用这个?创建一堆“模块”。在 ad-hoc 数组中注册初始化函数和销毁函数。在启动时处理阵列。(如果需要,您可以添加某种拓扑排序。)您不需要在任何地方都有模块的主列表,它会自动构建。或者,创建一个宏来将单元测试功能注册到测试套件中。同样,它创建了一个不需要“注册”的临时列表。

于 2021-12-19T05:50:24.793 回答