【问题标题】:How to declare a C array that takes up all free space in a memory section?如何声明一个占用内存部分中所有可用空间的 C 数组?
【发布时间】:2011-04-15 10:18:10
【问题描述】:

假设我有一个 128KB 的内存区域。在我的链接器指令中,我将此区域分为三个部分:

  • .section_text
  • .section_data
  • .section_bss

每个部分的大小在编译前是未知的,但我已经限制 .section_bss 在分配 .section_text 和 .section_data 后使用内存区域内的所有剩余空间。

有什么方法可以声明一个用完 .region_bss 中所有可用空间的 C 数组?假设它是唯一使用 .region_bss 的东西,因此它可以安全地使用整个区域。出于示例目的但显然是错误的:

char entire_bss[sizeof(.region_bss)];

这是我对一些预期响应的预先回答。首先,我知道 sizeof() 不能这样工作。我只是用它来获得一个想法。其次,假设这必须用数组而不是指针来完成(用指针解决是可能的并且相当简单)。第三,我知道我可以获得 .region_bss 的开始和结束地址,但我不知道有什么方法可以使用它们来调整我的数组大小。至少不是任何在 C 中有效的方式。

可能没有办法做到这一点,但我希望那里的一些天才已经弄清楚了。如果您可以使其与 Green Hills 工具集一起使用,则可加分。

【问题讨论】:

    标签: c arrays linker sizeof greenhills


    【解决方案1】:

    有什么方法可以声明一个用完.region_bss 中所有可用空间的C 数组?

    简短的回答是“不”。

    如果 GreenHills 使用带有 binutils 的 GNU 工具链并允许自定义 the linker script,那么您可以使用 PROVIDE 向应用程序命名空间添加一个变量,以标记 128K 块的结束。 (参见示例如何访问这些变量here)。这样你不会有一个固定大小的 C 数组,但程序将能够找到数组的结尾,因此数组的大小对于 C 程序来说通常是足够的。

    如果您想使用纯 C99 来实现这一点,那么您可能不走运,因为它是 highly unreliable,因为它不在标准中。

    【讨论】:

    • Green Hills 不使用 GNU 工具链。它具有 GNU 兼容性,但它是它自己的野兽。查看@PatrickSchlüter 的评论
    【解决方案2】:

    通常你这样做的方式是:

    extern char section_bss[];
    

    添加一些额外的东西,以便编译器、汇编器和链接器知道section_bss.section_bss(或类似名称)的别名。

    要获得大小,您可能希望对 bss 末尾的符号执行相同的操作并找出差异。

    【讨论】:

      【解决方案3】:

      不,你不能。这也很容易理解为什么。在编译阶段,没有 .bss 和 .data 的概念,它们是纯粹的链接器约定。编译器知道一些抽象概念(常量数据、静态数据、代码),但将它们映射到链接器部分只是一种约定,并且取决于链接器、操作系统和处理器甚至内存模型选项。例如,在构建位置无关代码时,通常会将常量放在代码段中。在嵌入式平台上,你有时不得不与这些事情作斗争,甚至不得不调整你的编码风格(我们曾经有一个基于 80186 处理器的模型,它是用 MS-C 5.1 编译器构建的,如果我们不能使用 @ 987654321@ 部分(全局、初始化变量和静态),因为工具链将它们放在 ROM 中。

      我们曾经通过在整个构建过程结束时修补生成的二进制文件解决了您的类似问题。我们从链接器生成的映射文件中提取了不同部分的已用内存(这是一个选项查找它),并从给定模型的内存大小中减去它(我们有 256K、512K 和 896K 模型)并设置一个具有正确值的全局常量。因此,所有对这个大小的引用都通过这个全局变量起作用,这一点很重要。然后我们的malloc/free实现使用了这个内存池。

      【讨论】:

        【解决方案4】:

        您要执行的操作将非常依赖于平台。您最好的选择可能是将数组声明为 extern char the_array[],end_of_array[];在 C 文件中,然后,也许在汇编语言源文件中,为 the_array 和 end_of_array 声明几个数据段。然后安排链接器规范,以便 the_array 将位于自下而上分配的内容的末尾,而 end_of_array 将位于自上而下分配的内容的开头,它们之间不会有其他任何东西。有可能——我在某些平台上做过——但仔细阅读链接器文档很重要,以确保链接器不会在你不期望的时候重新排列。

        【讨论】:

          【解决方案5】:

          怎么了

          extern char __ghsbegin_region_bss[];
          extern char __ghssize_region_bss[];
          #define entire_bss __ghsbegin_region_bss
          #define sizeof_entire_bss ((size_t)__ghssize_region_bss)
          

          ?我至少能想到一个你可能对这个答案不满意的原因,但它涉及到 C++ 模板元编程魔法(即,entire_bss 的类型没有正确的大小,所以模板取决于它的大小会以不同的方式解决)。只要你不使用数组的大小来做任何事情(在 C 中这是真的),这种方法应该没问题。

          请注意,__ghssize_region_bss 不是编译时常量——它直到链接时才被解析——所以在编译时没有办法 100% 将它放入数组类型的 [...] 中。

          请参阅 Green Hills 手册中“截面符号的开始、结束和大小”一章。

          【讨论】:

            猜你喜欢
            • 2013-04-26
            • 1970-01-01
            • 1970-01-01
            • 2012-04-29
            • 1970-01-01
            • 1970-01-01
            • 2021-02-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多