如何手动(以编程方式)将对象放置在我的多核项目中?

发布于 2024-12-20 02:39:02 字数 1138 浏览 4 评论 0原文

我正在为我们的 开发一个多核项目使用 gnu 工具链的嵌入式架构。在该架构中,所有独立核心共享相同的全局平面内存空间。每个内核都有自己的内部存储器,可以通过其全局 32 位地址从任何其他内核寻址。

没有实现操作系统,我们进行低级编程,但使用 C 而不是汇编。每个核心都有自己的可执行文件,通过单独的编译生成。我们当前用于核间通信的方法是通过计算目标核数据空间中对象的绝对地址。如果我们为所有内核构建相同的代码,则链接器会将对象定位在同一位置,因此访问远程内核中的对象只是更改当前内核中对象地址的高位位,并且进行交易。类似的概念允许我们共享位于外部 DRAM 中的对象。

当出现以下情况时,事情开始变得复杂:

  1. 两个内核中的代码不相同,因此对象可能不会分配在相似的地址中,

  2. 我们有时使用“主机”,它是另一个运行一些控制代码的处理器,需要访问内核中的对象以及外部存储器中的共享对象。

为了克服这个问题,我正在寻找一种在构建时放置变量的优雅方法。我想尽可能避免更改链接描述文件。然而,似乎在 C 级别,我只能使用 section 属性(太粗略)和 align 属性(这不保证确切的位置)。

一个可能的黑客方法是使用内联汇编来定义对象并显式放置它们(使用 .org.global 关键字),但它看起来有点丑陋(我们做了尚未实际测试这个想法...)

因此,问题如下:

  1. 是否有半标准方法或优雅的解决方案用于在 C 程序中手动放置对象?

  2. 我可以在代码中声明“uber”-extarnel 对象并让链接器使用另一个项目的可执行文件解析其地址吗?

这个问题描述了类似的情况,但用户引用了预先分配的资源(就像外围设备一样),其地址在构建时间之前就已知。

I am developing a mutlicore project for our embedded architecture using the gnu toolchain. In this architecture, all independent cores share the same global flat memory space. Each core has its own internal memory, which is addressable from any other core through its global 32-bit address.

There is no OS implemented and we do low-level programming, but in C instead of assembly. Each core has its own executable, generated with a separate compilation. The current method we use for inter-core communication is through calculation of absolute addresses of objects in the destination core's data space. If we build the same code for all cores, then the objects are located by the linker in the same place, so accessing an object in a remote core is merely changing the high-order bits of the address of the object in the current core and making the transaction. Similar concept allows us to share objects that are located in the external DRAM.

Things start getting complicated when:

  1. The code is not the same in the two cores, so objects may not be allocated in similar addresses,

  2. We sometimes use a "host", which is another processor running some control code that requires access to objects in the cores, as well as shared objects in the external memory.

In order to overcome this problem, I am looking for an elegant way of placing variables in build time. I would like to avoid changing the linker script file as possible. However, it seems like in the C level, I could only control placement up to using a combination of the section attribute (which is too coarse) and the align attribute (which doesn't guarantee the exact place).

A possible hack is to use inline assembly to define the objects and explicitly place them (using the .org and .global keywords), but it seems somewhat ugly (and we did not yet actually test this idea...)

So, here's the questions:

  1. Is there a semistandard way, or an elegant solution for manually placing objects in a C program?

  2. Can I declare an "uber"-extarnel objects in my code and make the linker resolve their addresses using another project's executable?

This question describes a similar situation, but there the user references a pre-allocated resource (like a peripheral) whose address is known prior to build time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

耶耶耶 2024-12-27 02:39:02

也许您应该尝试使用新操作员的“放置”标签。更确切地说,如果您已经分配/共享内存,您可以在其上创建新对象。请参阅:在预分配内存中创建对象

Maybe you should try to use 'placement' tag from new operator. More exactly if you have already an allocated/shared memory you may create new objects on that. Please see: create objects in pre-allocated memory

旧梦荧光笔 2024-12-27 02:39:02

您没有确切说明您将共享哪种数据,但假设它主要是固定大小的静态分配变量,我会将所有数据放在一个结构中并仅共享该数据。

这里的关键点是这个结构必须是共享代码,即使其他程序不是。可以附加额外的字段(可能带有版本字段,以便读者可以正确解释它),但不得删除或修改现有字段。结构已经被用作各处库之间的接口,因此可以依赖它们的布局(尽管在异构环境中需要多加小心,只要类型大小和对齐方式相同就可以了)。

然后,您可以通过以下任一方式共享结构:
a) 将它们放在一个特殊的部分中,并使用链接描述文件将其放在已知的位置;
b) 在静态数据中分配结构,并将指向该结构的指针放置在已知位置,例如在程序集启动文件中;或者
c) 与 (b) 相同,但在堆上分配结构,并在运行时将指针复制到已知的指针位置。其优点是可以为外部消费者预先调整指针,从而避免一定程度的混乱。

希望有帮助

You don't say exactly what sort of data you'll be sharing, but assuming it's mostly fixed-size statically allocated variables, I would place all the data in a single struct and share only that.

The key point here is that this struct must be shared code, even if the rest of the programs are not. It would be possible to append extra fields (perhaps with a version field so that the reader can interpret it correctly), but existing fields must not be removed or modifed. structs are already used as the interface between libraries everywhere, so their layout can be relied upon (although a little more care will be need in a heterogeneous environment, as long as the type sizes and alignments are the same you should be ok).

You can then share structs by either:
a) putting them in a special section and using the linker script to put that in a known location;
b) allocating the struct in static data, and placing a pointer to that at a known location, say in your assembly start-up files; or
c) as (b), but allocate the struct on the heap, and copy the pointer to the known pointer location at run-time. The has the advantage that the pointer can be pre-adjusted for external consumers, thus avoiding a certain amount of messing about.

Hope that helps

花之痕靓丽 2024-12-27 02:39:02

回答问题1:不,没有。

至于其余的,这在很大程度上取决于您使用的操作系统。在我使用嵌入式系统时,我们只有一个处理器的内存需要处理(基于 80186 和 68030),但可以从同一个二进制文件进行多任务处理。我们的工具链被扩展为以某种方式处理内存。
工具链看起来像这样(在 80186 上):

  • Microsoft C 16bit 或 Borland-C
  • Linker 链接到我们特定的 crt.o,它定义了一些特殊的符号和段。
  • Microsoft 链接器,生成 exe 和具有 MS-DOS 地址模式的映射文件
  • 调整可执行文件中的地址并生成平面二进制
  • 地址修补程序的定位器。
  • EPROM 刻录器(后来的闪存加载器)。

在我们的程序集中,我们定义了一个始终位于数据段开头的符号,并使用来自找到的映射文件的硬编码值修补了二进制文件。这允许库将所有剩余内存用作堆。

事实上,如果您没有定位器(Linux 上的 elf 加载器或 Windows 上的 exe/dll 加载器)上的控件,那么您就完蛋了。

Response to question 1: no, there isn't.

As for the rest, it depends very much of the operating system you use. On our system at the time I was in embedded, we had only one processor's memory to handle (80186 and 68030 based), but had multi-tasking but from the same binary. Our tool chain was extended to handle the memory in a certain way.
The toolchain looked like that (on 80186):

  • Microsoft C 16bit or Borland-C
  • Linker linking to our specific crt.o which defined some special symbols and segments.
  • Microsoft linker, generating an exe and a map file with a MS-DOS address schema
  • A locator that adjusted the addresses in the executable and generated a flat binary
  • Address patcher.
  • An EPROM burner (later a Flash loader).

In our assembly we defined a symbol that was always at the beginning of data segment and we patched the binary with a hard coded value coming from the located map file. This allowed the library to use all the remaining memory as a heap.

In fact, if you haven't the controle on the locator (the elf loader on linux or the exe/dll loader in windows) you're screwed.

腻橙味 2024-12-27 02:39:02
  1. 你在这里很不走寻常路 - 不要指望任何“标准”的东西:)
  2. 这个答案建议一种将原始地址列表传递给链接器的方法。链接外部可执行文件时,生成链接器映射文件,然后对其进行处理以生成此原始符号表。

您还可以尝试将整个程序(所有核心的程序)链接到单个可执行文件中。使用节定义和链接描述文件将每个内核的程序放入其内部存储器地址空间;您可以单独构建每个核心的程序,将其增量链接到单个 .o 文件,然后使用 objcopy 重命名其部分以包含链接器脚本的核心 ID,以及 如果您要跨多个核心复制相同的代码,请重命名(隐藏)私有符号。最后,手动将每个内核的起始地址提供给引导程序代码,而不是使用正常的起始符号。

  1. You're well off the beaten path here - don't expect anything 'standard' for any of this :)
  2. This answer suggests a method of passing a list of raw addresses to the linker. When linking the external executable, generate a linker map file, then process it to produce this raw symbol table.

You could also try linking the entire program (all cores' programs) into a single executable. Use section definitions and a linker script to put each core's program into its internal memory address space; you can build each core's program separately, incrementally link it to a single .o file, then use objcopy to rename its sections to contain the core ID for the linker script, and rename (hide) private symbols if you're duplicating the same code across multiple cores. Finally, manually supply the start address for each core to your bootstrap code instead of using the normal start symbol.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文