繁体   English   中英

macOS如何为进程分配堆栈和堆?

[英]How does macOS allocate stack and heap for a process?

我想知道macOS如何为进程分配堆栈和堆内存,即macOS中进程的内存布局。 我只知道将mach-o可执行文件的段加载到页面中,但是找不到与进程的堆栈或堆区域相对应的段。 是否有任何相关文件?

堆栈和堆只是内存。 使堆栈成为堆栈或堆或堆的唯一想法是访问堆栈的方式。 堆栈和堆的分配方式与所有内存相同:将页面映射到逻辑地址空间。

让我们退后一步-Mach-o格式描述了将二进制段映射到虚拟内存的方法。 重要的是,您提到的内存页具有读写和执行权限。 如果它是可执行文件(即不是dylib),则它必须包含__PAGEZERO段,完全没有任何权限。 这是一个安全保护区域,可以防止意外访问虚拟内存的低地址(此处臭名昭著的Null指针异常,以及尝试访问零内存地址的情况)。
紧随其后的是__TEXT读取可执行文件(通常不包括写操作)段,该段在虚拟内存中将包含文件表示本身。 这意味着所有可执行代码都位于此处。 也是不变的数据,例如字符串常量。
顺序可能有所不同,但是通常接下来您将遇到__LINKEDIT只读段。 这是dyld用来设置外部加载函数的段,此处范围太广,无法涵盖,但有关该主题的答案很多。
最后,我们有一个可读可写的__DATA段,它是进程可以实际写入的第一个位置。 这用于全局/静态变量,即由dyld填充的调用的外部地址。

通过LC_UNIXTHREAD或在现代MacOS( LC_MAINLC_MAIN启动时,我们大致介绍了该过程的初始设置。 这将启动进程主线程 每个线程必须包含其自己的stack 它的创建由操作系统处理(包括分配)。 请注意,到目前为止,该过程根本不了解堆 (正是操作系统在为准备堆做了大量工作)。

因此,总结一下,到目前为止,我们有2个独立的内存源-代表Mach-o结构(大小是固定的,并由可执行结构确定)的进程内存和主线程堆栈(也具有预定义的大小)。 该过程将运行一个类似C的主函数,任何声明的局部变量都将移动线程堆栈指针 ,同样,对函数的任何调用(局部和外部)至少应为返回地址设置堆栈框架。 访问全局/静态变量将直接引用__DATA段虚拟内存。 在x86-64程序集中保留堆栈空间如下所示:

sub rsp,16

也有一些重大的系统V / AMD64 ABI(其包括的MacOS)像这样堆叠的对准要求SO anwers 一个

创建的任何新线程都将具有其自己的堆栈,以允许为局部变量和调用函数设置堆栈框架。

现在我们可以讨论分配-通过libSystem (又名MacOS C标准库)提供malloc / free可以减轻分配。 在内部,这是通过mmapmunmap系统调用(用于管理内存页面的内核API)处理的。 直接使用这些系统调用是可能的,但是可能效率很低,因此malloc / free使用内部内存池来限制系统调用的数量(这样做的成本很高)。

您在评论中提到的地址更改是由以下原因引起的:

  1. ASLR aka PIE(与位置无关的代码),用于过程内存,这是一种安全措施,用于随机化虚拟内存的启动
  2. 操作系统正在准备的线程本地堆栈

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM