malloc() 分配的内存区域是什么?

malloc() 分配的内存区域是什么?

我正在使用库编写一个多线程 C 程序pthread。程序malloc()从线程和主线程调用。当我检查返回的内存地址时malloc(),主线程中返回的地址malloc()是通常的地址(如0x80874a0),这是程序的堆部分的地址。但是malloc()另一个线程(由 创建)返回的地址pthread_create()有点不寻常,地址位于地址空间的高位(0x7ffa87000a60 看起来有点像堆栈部分中的地址)。分析该线程的某个堆栈变量的地址后,看起来返回的地址位于malloc()该线程的堆栈附近。

我很困惑,因为据我所知程序的一部分由该程序中的所有线程共享,因此任何调用都malloc()应该返回靠近在一起的地址。它应该返回从一个地址开始的地址。但可以肯定的是事实并非如此。

答案1

根据它的定义,您从 malloc 获得的是“堆”。所以,所有这些都是堆。

GNU libc 的malloc文档将自己描述为man malloc在“arena”中执行此操作 ( ):

为了可扩展地处理多线程应用程序中的内存分配,如果检测到互斥锁争用,glibc 会创建额外的内存分配区域。每个 arena 都是一个大的内存区域,由系统内部分配(使用brk(2)mmap(2)),并使用自己的互斥体进行管理。

我很困惑,因为据我所知,程序的堆部分由该程序中的所有线程共享,

“堆”通常不是我最喜欢的术语。它合并了不同的概念:

  • (是一种数据结构。内核中的内存管理数据结构和/或由malloc堆创建的内存管理数据结构是否是堆都不是给定的(通常不是。)因此,这已经是一个混乱的根源。)
  • 在具有内存保护和虚拟地址的操作系统中,指的是进程空间的某个区域,从中malloc取出一块,并在内部将其标记为正在使用(无论是在单独的表中,堆中,...,还是在进程开始之前的标头中)本身)。因此,这是一个含糊不清的术语。您可以brk根据需要扩展进程虚拟内存,而无需实际占用物理内存。因此,您可以为自己获得额外的 10 GB 空间,然后使用两个不同的起始地址(间隔 5 GB)来分配两个不同的内存区域。这是一个堆,两个区域吗?两个区域,每个区域都有自己的堆?文学界对此并不认同。如果只是用 扩展虚拟内存空间的末尾brk,我决定mmap在两个地方的某个地方取消支持内存,该怎么办?那么这是两堆吗?

所以,它实际上可以归结为“堆”的含义你的书,以及您的具体malloc实现如何实际保留内存。

答案2

对于“大”分配(与页面大小相比较大),GNU C 库的实现malloc 用途mmap。这可能就是您在这里看到的 - 第一个分配是使用 的mallocarenas 处理的,第二个分配是使用mmap(使用更高的地址)处理的。

内核中进程内存测量更新的速度/频率如何?来说明这种行为。

相关内容