Memory management 数据段对进程的堆栈分配及其占用
抱歉,如果这些问题是愚蠢的,但它们真的让我困惑! 根据elf标准,二进制文件分为文本段(包含代码和RO数据)和数据段(包含RW和BSS),当程序执行和进程创建时,数据段加载到内存中,这些段为进程执行的环境准备提供信息。 问题是,当我在进程创建过程中不提供堆栈大小时,如何确定要分配给进程的堆栈数量? 此外,使用数据段,我们可以确定进程需要多少内存(对于全局变量),但一旦分配了内存,如何使用分配内存中的地址空间进行变量映射? 最后,这与分散载荷有关系吗?我认为情况并非如此,因为在将图像加载到内存中时,分散加载是完成的,一旦控制传递给操作系统,分配给可执行文件或应用程序的内存将由操作系统自己处理! 我知道这些问题太多了,但我们将非常感谢您的帮助。 如果你能提供任何参考书或链接,我可以在其中详细研究这一点,这也是感谢。Memory management 数据段对进程的堆栈分配及其占用,memory-management,process,operating-system,Memory Management,Process,Operating System,抱歉,如果这些问题是愚蠢的,但它们真的让我困惑! 根据elf标准,二进制文件分为文本段(包含代码和RO数据)和数据段(包含RW和BSS),当程序执行和进程创建时,数据段加载到内存中,这些段为进程执行的环境准备提供信息。 问题是,当我在进程创建过程中不提供堆栈大小时,如何确定要分配给进程的堆栈数量? 此外,使用数据段,我们可以确定进程需要多少内存(对于全局变量),但一旦分配了内存,如何使用分配内存中的地址空间进行变量映射? 最后,这与分散载荷有关系吗?我认为情况并非如此,因为在将图像加载到内存中时
谢谢你一吨!:)
问题是,当我在进程创建过程中不提供堆栈大小时,如何确定要分配给进程的堆栈数量?
创建新进程时,execve()
系统调用用于将新程序作为进程映像从当前运行的进程映像加载到内存中。这意味着当加载新程序时,将替换旧的.text
,.data
段,堆
并重置堆栈
。现在ELF可执行文件被映射到内存地址空间,使堆栈空间通过环境数组和参数数组初始化为main()
子例程()下的In()过程调用处理以下任务:
mm_struct
的新实例
main()
例程中。函数调用子集的每个环境,包括参数和局部变量,在调用发生时都会动态地存储或推送到堆栈内存区
-----------------
| | <--- Top of the Stack
| environmental |
| variables and |
| the other |
| parameters to |
| main() |
_________________ <--- Stack Pointer
| |
| Stack Space |
| |
使用readelf
显示.data
节头,如下所示
$readelf -a elf
...
Section Headers:
[26] .data PROGBITS 00000000006c2060 000c2060
00000000000016b0 0000000000000000 WA 0 0 32
[27] .bss NOBITS 00000000006c3720 000c3710
0000000000002bc8 0000000000000000 WA 0 0 32
...
$readelf -x 26 elf
Hex dump of section '.data':
0x006c2060 00000000 00000000 00000000 00000000 ................
0x006c2070 0a000000 00000000 00000000 00000000 ................
...
让我们使用GDB来查看这些部分包含的内容
(gdb) disassemble 0x006c2060
Dump of assembler code for function `data_start`:
0x00000000006c2060 <+0>: add %al,(%rax)
0x00000000006c2062 <+2>: add %al,(%rax)
0x00000000006c2064 <+4>: add %al,(%rax)
0x00000000006c2066 <+6>: add %al,(%rax)
End of assembler dump.
上述反汇编转储全局变量value1
的地址,初始化为
10但在接下来的地址中,我们看不到全局未初始化变量value2
让我们看看打印value2
的地址
(gdb) p &value2
$1 = (int *) 0x6c5eb0
(gdb) info symbol 0x6c5eb0
value2 in section **.bss**
(gdb) disassemble 0x6c5eb0
Dump of assembler code for function `value2`:
0x00000000006c5eb0 <+0>: add %al,(%rax)
0x00000000006c5eb2 <+2>: add %al,(%rax)
End of assembler dump.
(gdb)p&value2
$1=(整数*)0x6c5eb0
(gdb)信息符号0x6c5eb0
第**.bss节中的值2**
(gdb)拆解0x6c5eb0
函数“value2”的汇编程序代码转储:
0x00000000006c5eb0:添加%al,(%rax)
0x00000000006c5eb2:添加%al,(%rax)
汇编程序转储结束。
塔达!分解value2
的引用指针表明变量存储在.bss
节中。这解释了未初始化的全局变量如何映射到进程内存空间
最后,这与分散负载有关系吗代码>
没有
(gdb) disassemble 0x006c2070
Dump of assembler code for function `value1`:
0x00000000006c2070 <+0>: or (%rax),%al
0x00000000006c2072 <+2>: add %al,(%rax)
End of assembler dump.
....
(gdb) p &value2
$1 = (int *) 0x6c5eb0
(gdb) info symbol 0x6c5eb0
value2 in section **.bss**
(gdb) disassemble 0x6c5eb0
Dump of assembler code for function `value2`:
0x00000000006c5eb0 <+0>: add %al,(%rax)
0x00000000006c5eb2 <+2>: add %al,(%rax)
End of assembler dump.