内存段在哪里定义?

4
我刚学习了不同的内存段,如Text、Data、Stack和Heap。我的问题是:
1- 这些段之间的边界是在编译器还是操作系统中定义的?
2- 编译器或操作系统如何知道哪些地址属于每个段?我们需要在任何地方定义它吗?

2
C语言本身与这些完全无关。 - John Bollinger
1
由于此标签为嵌入式,因此与操作系统相关的讨论可能不如这篇文章微控制器不同内存类型中存储的内容是什么?有用。 - Lundin
3个回答

7
这个答案是从一个更专门的嵌入式系统的角度来看,而不是像Linux这样的通用计算平台。
这些部分之间的边界是在哪里定义的?是在编译器还是操作系统中?
既不是编译器也不是操作系统。是链接器决定内存部分的位置。编译器从源代码生成目标文件。链接器使用链接器脚本文件将目标文件定位在内存中。链接器脚本(或链接器指令)文件是项目的一部分,并标识各种内存类型(如ROM和RAM)的类型、大小和地址。链接程序使用链接器脚本文件中的信息来了解每个内存从哪里开始。然后,链接器将每种类型的内存从一个目标文件定位到适当的内存部分。例如,代码放在.text部分中,通常位于ROM中。变量放在.data或.bss部分中,位于RAM中。堆栈也放在RAM中。当链接器填充一个部分时,它会了解到该部分的大小,并且可以知道下一个部分从哪里开始。例如,.bss部分可以从.data部分结束的地方开始。
堆和栈的大小可以在链接器脚本文件中指定,也可以在IDE的项目选项中指定。
嵌入式系统的IDE通常在创建项目时自动提供通用链接器脚本文件。通用链接器文件适用于许多项目,因此您可能永远不需要自定义它。但是随着您进一步定制目标硬件和应用程序,您可能会发现需要自定义链接器脚本文件。例如,如果向板子中添加外部ROM或RAM,则需要将有关该内存的信息添加到链接器脚本中,以便链接器知道如何在那里定位。
链接器可以生成描述每个部分在内存中定位方式的映射文件。默认情况下可能不会生成映射文件,如果您想要查看它,则可能需要打开构建选项。
编译器或操作系统如何知道哪些地址属于每个部分?
我不认为编译器或操作系统实际上知道这些信息,至少不能查询它们以获取信息。编译器在链接器定位内存部分之前已经完成了其工作,因此编译器不知道该信息。操作系统呢?嵌入式应用程序甚至可能不使用操作系统。操作系统只是提供服务给应用程序的一些代码。操作系统不知道也不关心内存部分的边界在哪里。所有这些信息都已经通过可执行代码烘焙到运行操作系统之时。
我们应该在哪里定义它?
查看链接器脚本(或链接器指令)文件并阅读链接器手册。链接器脚本是链接器的输入,提供内存的大致轮廓。链接器将所有东西定位在内存中,并确定每个部分的范围。

4
对于你的问题: 这些区域之间的边界如何定义?是在编译器还是操作系统中? 答案是操作系统。
对于可执行代码 (.text 段)、变量 (.data 段) 以及其他程序段的布局,没有普遍通用的寻址方案。不过,程序本身的布局是根据将要执行程序的系统 (操作系统) 规范化的。 编译器或操作系统如何知道哪些地址属于每个部分?我们需要在任何地方定义它吗? 我把你的问题分为了三个问题: 关于文本 (代码) 和数据段及其限制? 文本和数据是由编译器准备的。编译器的要求是确保它们是可访问的,并将它们打包在地址空间的较低部分中。可访问的地址空间将受到硬件的限制,例如如果指令指针寄存器是32位,则文本地址空间将为4 GiB。 关于堆段和限制?它是总可用 RAM 内存吗? 在文本和数据之后,上面的区域就是堆。使用虚拟内存技术,堆可以实际上接近最大地址空间大小。 堆和栈是否具有静态大小限制? 进程地址空间中的最后一个段是栈。栈占用地址空间的末尾部分,从末尾开始向下增长。
由于堆向上增长、栈向下增长,它们基本上相互限制。此外,由于这两种类型的段都可写,所以跨越边界并不总是一种违规行为,因此可能会出现缓冲区或栈溢出。现在有机制可以阻止这些情况发生。
每个进程都有一个堆 (栈) 的固定限制。这个限制可以在运行时更改 (使用 brk()/sbrk())。基本上,当进程需要更多的堆空间而已经用完了分配的空间时,标准库将向操作系统发出调用。操作系统会分配一页,通常由用户库来管理程序使用。也就是说,如果程序要求1 KiB,操作系统将提供额外的4 KiB,库将提供1 KiB给程序,并为以后程序下次请求更多空间时保留3 KiB。
大多数情况下,布局将是文本、数据、堆 (向上增长)、未分配空间和最终栈 (向下增长)。它们都共享同一地址空间。

3

这些部分的定义与操作系统松散地相关。例如,在Linux上,您有ELF,而在Mac OS上,您有Mach-O

99.9%的情况下,作为程序员,您不需要显式地定义这些部分。编译器知道在哪里放置每个部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接