【问题标题】:What does __section( ) mean in linux kernel source__section() 在 linux 内核源代码中是什么意思
【发布时间】:2018-01-14 12:38:49
【问题描述】:

我在某些操作系统内核中看到以下代码。但是我不明白__section的使用方式,也不知道这段代码是什么意思。

#define KEEP_PAGER(sym) \
    extern const unsigned long ____keep_pager_##sym; \
    const unsigned long ____keep_pager_##sym  \
        __section("__keep_meta_vars_pager") = (unsigned long)&sym

【问题讨论】:

  • 您是否尝试过在代码中搜索,看看它是否在任何地方声明或定义?
  • 谢谢,明白了。它在另一个#define 中定义。我在徘徊为什么它没有被属性包围。我终于找到了以下#define:#define __section(x) __attribute__((section(x)))

标签: c linux gcc linux-kernel compiler-optimization


【解决方案1】:

它是特定的 linux 内核 C macro definition 包裹在 GCC extension 周围,指定了 atttribute to use for an object。这是编写 section 属性定义的更短的方式

从历史上看,Linux 内核一直是 written specifically for building with the GCC compiler,并广泛使用低级扩展来执行特定的硬件操作和优化。

section 属性专门用于确定用它标记的对象的存储位置。 ELF binary format 将目标文件排列成命名的部分,并使用这样的属性允许程序员更精确地指定标记对象的信息将放置在目标对象中的位置

多年来,人们一直致力于提高这些编译器扩展在不同编译器之间的兼容性,以及使 linux 可以与其他编译器一起编译(如果您查看 the linux header file where the macro is defined,您会发现它充满了各种编译器功能的条件指令)。像这样的宏可能是一种有用的方法,可以为跨不同编译器实现的低级功能提供可移植的内部 API。

内核和内核驱动程序 C 代码通常与物理硬件实现的直接细节有关,并且需要以应用级 C 代码很少这样做的方式明确编译器二进制输出。

Linux内核使用命名部分的一个例子是init handling - 仅在启动期间使用的函数和数据被分组到一个内存部分中,一旦启动完成就可以轻松释放 - 你可能熟悉在 linux 引导序列结束时,引导消息类似于“释放未使用的内核内存:...”

【讨论】:

  • 是的,它确实是一个宏包装属性,我将扩展那个解释
  • 这就是为什么发明自己的自制宏语言是一个坏主意的原因。这个宏太天真了,因为其他一些编译器可能会使用#pragma 之类的东西作为内存部分,在这种情况下,这个宏将不起作用。无论如何,Linux 永远不会在 GCC 之外的任何其他编译器上工作,只是过于依赖编译器特定的功能。
【解决方案2】:

如果没有定义,很难判断 __section 到底是什么,但它可能是一个可变的“节”属性。它用于使编译器将变量放入与“bss”或“data”不同的部分。详情请见GCC documentation。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-08
    • 2012-03-29
    • 2016-05-23
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    相关资源
    最近更新 更多