【问题标题】:How is the initial value of the stack pointer determined?堆栈指针的初始值是如何确定的?
【发布时间】:2012-07-21 16:18:56
【问题描述】:

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

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

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

virtual memory          (kbytes, -v) unlimited

现在,unlimited 肯定是指可用于寻址的有限位数所带来的技术限制(在 64 位 Linux 上,我记得是 48 位?!)

那么,除非有不同的ulimit 应用,否则堆栈指针大致初始化为(vmem 开头 + 2^48 位)就这么简单吗?

【问题讨论】:

  • 在某些系统中,SP 初始化为 0,因为push 会先递减地址,然后再写入内存。但是我不知道Linux现在使用什么算法。另外,出于安全原因,堆栈指针的地址可能不再固定。
  • 当递减零时,您会得到一个int 下溢,它会回滚到最大int 数字。这就是您所说的系统如何确定堆栈指针与开始的距离。这是你说的吗?
  • @Frank:你会得到适当类型的下溢。对于与 32 位 int 不同的 64 位指针。
  • 是的,当然,int 不会在 0 处下溢。我的意思是 C 中的 uintsize_t 等效项。在 64 位上它是无符号长的。
  • @Frank:是的。 CPU 架构将确保您获得尽可能大的地址。然后,VM 表会将这个虚拟地址映射到实际内存中的某个页面。

标签: linux memory 64-bit stack


【解决方案1】:

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

  • 对于现代 Linux 系统,单线程程序的初始堆栈基础由内核 Address Space Layout Randomization (ASLR) feature 控制。
  • 在 ASLR 之前的远古时代,我认为主线程的堆栈曾经位于 32 位 Linux 的高固定地址。对于 ASLR 之前的 64 位(或者如果您禁用它),它可能位于远离其他一切的固定地址,但如果该地址取决于内核版本,我不会感到惊讶。
  • 对于多线程 Linux 程序,堆栈由 glibc 在启动线程的 clone() 调用之前使用 mmap 分配(请参阅:nptl/allocatestack.c
  • 在 32 位单线程 AIX 上,堆栈和堆(受 sbrk 控制)曾经共存于 16 256 mb 段之一(我忘了是哪一个。)我记得有很多乐趣如果您使用允许堆栈增长为堆的选项进行编译,则所有人都可以使用 em>。
  • ...

【讨论】:

    猜你喜欢
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-27
    • 2021-11-28
    • 2017-09-24
    • 2016-11-09
    • 2015-04-11
    • 1970-01-01
    相关资源
    最近更新 更多