3

假设我有一个 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 工具集一起使用,则可以加分。

4

5 回答 5

2

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

简短的回答是“不”。

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

如果您想使用纯 C99 来实现这一点,那么您可能会很不走运,因为它非常不可靠,因为它没有被标准涵盖。

于 2010-09-21T21:27:05.730 回答
2

通常你这样做的方式是:

extern char section_bss[];

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

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

于 2010-09-21T21:00:40.443 回答
2

No you can't. It's also easy to understand why. At the compilation phase there is no concept of .bss and .data these are pure linker conventions. The compiler knows some abstract concepts (const data, static data, code), but the mapping of them to the linker section is only a convention, and depending on linker, OS and processor or even memory model options. When building position independend code, often the constants are put in the code segment for example. On embedded platforms you sometime have to struggle with these things and even have to adapt your coding style because of that (we had once a model based in 80186 processors that were built with MS-C 5.1 compiler, were we couldn't use the .data section (global, initialized variables and statics) because the toolchain put them in the ROM.

We solved once a similar problem of yours by patching the generated binary at the end of the whole build process. We extracted the used memory of the different section from the map file generated by the linker (it's an option look it up), and subtracted it from the memory size of the given model (we had 256K, 512K and 896K models) and set one of the global constants with the right value. It was thus important that all references to this size work via this global variable. This memory pool was then used by our implementation of malloc/free.

于 2010-09-22T06:09:01.670 回答
0

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

于 2010-09-21T21:59:57.877 回答
0

有什么问题

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 手册中的“截面符号的开始、结束和大小”一章。

于 2012-09-06T18:18:08.630 回答