6

程序加载器初始化/加载text,data+bss区域。这些分配在靠近开始的进程的虚拟地址空间中。然后堆会向更大的地址增长(在 data+bss 之后)。堆栈从较大的地址向较低的地址增长。

我想知道堆栈指针的初始值是如何确定的。

如果我要求每个进程的虚拟地址限制(ulimit -v)我得到

virtual memory          (kbytes, -v) unlimited

现在,这unlimited当然是指有限数量的可用于寻址的技术限制(在 64 位 Linux 上,我记得 48 位?!)

那么,除非应用不同ulimit的应用程序,否则堆栈指针被粗略地初始化为(vmem + 2 ^ 48 位的开始)就这么简单吗?

4

1 回答 1

1

这是一个高度依赖平台的问题,取决于您正在运行的程序的位数、正在使用的操作系统版本、系统配置选项、程序是单线程还是多线程以及其他因素:

  • 对于现代 Linux 系统,单线程程序的初始堆栈基础由内核地址空间布局随机化 (ASLR) 功能控制。
  • 在 ASLR 之前的古代,我认为主线程的堆栈曾经位于 32 位 Linux 的高固定地址。对于 ASLR 之前的 64 位(或者如果您禁用它),它可能位于远离其他一切的固定地址,但如果该地址取决于内核版本,我不会感到惊讶。
  • 对于多线程 Linux 程序,堆栈是在启动线程的 clone() 调用之前由 glibc 使用 mmap 分配的(参见:nptl/allocatestack.c
  • 在 32 位单线程 AIX 上,堆栈和堆(受 sbrk 控制)曾经共存于 16 256 mb 段之一(我忘了是哪一个。)我记得如果你编译的话,所有人都会有很多乐趣带有允许堆栈增长为堆的选项。
  • ...
于 2019-10-27T03:10:51.393 回答