堆,堆栈,文本等不同的段如何与物理内存相关?

vij*_*231 18 c stack memory-management elf

  1. 编译C程序并创建目标文件(ELF)时.目标文件包含不同的部分,如bss,数据,文本和其他段.我知道ELF的这些部分是虚拟内存地址空间的一部分.我对吗?如果我错了,请纠正我.

  2. 此外,将存在与编译的程序相关联的虚拟存储器和页表.页表在加载程序时将ELF中存在的虚拟内存地址与实际物理内存地址相关联.我的理解是否正确?

  3. 我在创建的ELF文件中读到,bss部分只保留未初始化的全局变量的引用.这里未初始化的全局变量是指在声明期间未初始化的变量?

  4. 另外,我读到局部变量将在运行时(即堆栈中)分配空间.那么它们将如何在目标文件中引用?

  5. 如果在程序中,有特定的代码段可用于动态分配内存.如何在目标文件中引用这些变量?

我很困惑,目标文件的这些不同部分(如文本,rodata,数据,bss,堆栈和堆)是物理内存(RAM)的一部分,所有程序都在其中执行.但我觉得我的理解是错误的.当进程或程序执行时,这些不同的段如何与物理内存相关?

P.T*_*.T. 19

1.正确,ELF文件列出了操作系统应将ELF文件内容复制到的进程的虚拟地址空间中的绝对或相对位置.(bss只是一个位置和一个大小,因为它应该全为零,所以不需要在ELF文件中实际存在零).请注意,位置可以是绝对位置(如虚拟地址0x100000或相对位置,如文本结尾后的4096字节).

2.虚拟内存定义(保存在页表中并将虚拟地址映射到物理地址)与编译的程序无关,而是与"进程"(或"任务"或操作系统调用它的任何内容)相关联,表示运行该程序的实例.例如,可以将单个ELF文件加载到两个不同的进程中,位于不同的虚拟地址(如果ELF文件是可重定位的).

3.您正在使用的编程语言定义哪个未初始化状态进入bss,并且显式初始化.请注意,BSS不会包含"引用",以这些变量,它存储支持这些变量.

4.堆栈变量从生成的代码中隐式引用.ELF文件中没有任何关于它们(甚至是堆栈)的明确说明.

5.与堆栈引用一样,堆引用隐含在ELF文件中生成的代码中.(它们都存储在通过调用sbrk或等效的虚拟地址空间创建的内存中.)

ELF文件向操作系统解释如何为程序实例设置虚拟地址空间.不同的部分描述了不同的需求.例如".rodata"说我想存储只读数据(而不是可执行代码).".text"部分表示可执行代码."bss"是用于存储应由OS归零的状态的区域.虚拟地址空间意味着程序可以(可选地)依赖于启动时所期望的位置.(例如,如果它要求.bss位于地址0x4000,则操作系统将拒绝启动它,否则它将在那里.)

请注意,这些虚拟地址由OS管理的页表映射到物理地址.ELF文件的实例不需要知道使用哪些物理页面所涉及的任何细节.


Str*_*rix 5

我不确定1、2和3是否正确,但我可以解释4和5。

4:它们是通过距堆栈顶部的偏移量来引用的。执行函数时,栈顶会增加,为局部变量分配空间。编译器确定堆栈中局部变量的顺序,因此编译器现在知道变量距堆栈顶部的偏移量是多少。

物理内存中的堆栈位置是颠倒的。堆栈的开头通常具有可用的最高内存地址。当程序运行并为局部变量分配空间时,堆栈顶部的地址会递减(并且可能导致堆栈溢出 - 与较低地址上的段重叠:-))

5:使用指针 - 动态分配的变量的地址存储在(本地)变量中。这对应于在 C 中使用指针。

我在这里找到了很好的解释:http://www.ualberta.ca/CNS/RESEARCH/LinuxClusters/mem.html


oua*_*uah 2

使用 size 命令检查 ELF 时看到的不同部分(.text、.bss、.data 等)的所有地址:

$ size -A -x my_elf_binary
Run Code Online (Sandbox Code Playgroud)

是虚拟地址。带有操作系统的 MMU 执行从虚拟地址到 RAM 物理地址的转换。