【问题标题】:Why is there no content for the .bss section in an object (ELF) file?为什么对象 (ELF) 文件中的 .bss 部分没有内容?
【发布时间】:2018-02-24 19:42:45
【问题描述】:

这个问题让我很困惑。据我所知,.bss 部分用于保存已初始化但尚未使用的数据。但是我不明白这里的“内容”是什么意思,为什么这里没有内容?

感谢您的帮助!

【问题讨论】:

  • 全为0,所以不需要任何显式内容。也就是说,它被初始化为 0,而不是未初始化,而不是初始化为“有趣”的东西。
  • 没有它很好。因为定义一些较大的静态数组会自动使您的二进制文件至少具有该大小。
  • @SteveSummit 在任何情况下都会是 0 吗?
  • 请在问题中添加一些示例代码/文本
  • Will it always be 0 in any situation? 初始化为0。但在运行时可能变成任意值。

标签: c operating-system elf


【解决方案1】:

快速响应是:嗯,没有内容可以填充.bss,因此将任何数据放在与该部分相关的可执行文件上是没有意义的。仅存储变量的位置,但属于另一个 ELF 部分。

.bss 部分是您的程序具有所有未初始化变量的地方(默认情况下全部初始化为零)链接器只需要知道该区域的实际大小和实际变量位置,而不是值,因为它的内容是显而易见的,与放在那里的变量的性质或分布无关。

当您的程序被加载时,内核通常会为程序的不可修改文本分配一个只读段(.text 部分),并将初始化的const 变量的内容(.rodata部分)所以如果你试图在那里修改一些东西,你会得到一个例外。然后是初始化数据部分,其中包含程序所有已初始化变量(.data 部分)和未初始化变量(.bss 部分)的初始值

数据段(看看我如何称呼不同的段和加载段)有更多空间,.data.bss 段的总和,以保存所有变量(都包括在内,这就是原因它使用它的长度),但是.data 部分的内容必须从文件中填充,.bss 部分的内容不需要,因为在允许用户进程之前,所有内容都由操作系统清零访问分配的段。对于小型系统而言,情况并非如此,操作系统不会用零填充数据......但是在那里,编译器会添加一些代码将所有 .bss 段归零,因此,再次,无需复制任何数据可执行文件。

这种行为的历史(和主要)原因是内核分配的必须与您的程序一起加载的页面出于安全原因被清除为零(因此您不能幸运地获得一个充满其他用户密码的页面,或其他敏感信息),因此没有理由再次用零填充它,并且不需要在那里复制任何内容,也没有理由在可执行文件上放置任何内容。内核维护的页面通常只有在将要提供给用户时才归零,但会维护(因为它们是为此目的而设计的)信息,直到它们被覆盖。

【讨论】:

  • 你的回答很有帮助!非常感谢!
【解决方案2】:

BSS(由符号开始的块)部分中没有内容,因为它会浪费存储空间。 BSS 的内容全为零,在调用main 之前由启动代码清除。将 BSS 视为运行长度压缩的字节块。解压缩该块只需要知道值 (0) 和长度,它们存储在 BSS 的 ELF 条目中。

您对“[已]初始化但尚未使用的数据”的概念有点偏离。考虑到 ELF 文件中的 all 部分以某种方式“尚未使用”。文本段可能会或可能不会被使用(它可能包含死/无法访问的代码)。数据段可能会或可能不会被使用(您可以定义代码从不使用的对象)。

【讨论】:

  • 更准确地说,它可能没有被“清除”,但内容是从 COW 零页面按需映射的
  • @AnttiHaapala 假设一个特定的实现。我为一个不使用 MMU 的 SPARC 嵌入式应用程序编写了启动程序,它明确清除了 BSS。
  • ^在大多数无操作系统的裸机系统上都是如此
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-06
  • 2011-10-01
  • 1970-01-01
  • 2020-12-18
相关资源
最近更新 更多