我对Window堆分配和堆堆栈等很清楚。尽管不是Linux的新手,但我不太清楚它是如何工作的?

在Windows上:

  • 在进程开始时,操作系统创建一个默认的堆,称为Process堆。如果不使用其他堆,则使用Process堆分配块。
  • 语言运行时间也可以在一个进程中创建单独的堆。 (例如,C运行时会创建自己的堆。)
  • 除了这些专用堆之外,应用程序或许多已加载的动态链接库(DLL)之一可能会创建并使用单独的堆,称为专用堆
  • 这些堆位于所有虚拟内存系统中的操作系统的Virtual Memory Manager之上。
  • a)C / C++运行时(CRT)分配器:提供malloc()和free()以及new和delete运算符。
    b)作为初始化的一部分,CRT为其所有分配创建一个额外的堆(此CRT堆的句柄内部存储在CRT库中的全局变量_crtheap中)。
    c)CRT创建自己的私有(private)堆,该堆位于Windows堆的顶部。
    d)Windows堆是围绕Windows运行时分配器(NTDLL)的薄层。
    e)Windows运行时分配器与虚拟内存分配器进行交互,虚拟内存分配器保留并提交操作系统使用的页面。

  • 我们的DLL和exe链接到多线程静态CRT库。我们创建的每个DLL和exe文件都有一个自己的堆,即_crtheap。分配和取消分配必须从各自的堆中进行。从DLL动态分配的,不能从可执行文件中取消分配,反之亦然。

    使用/ MD或/ MDd在DLL和exe中编译我们的代码,以使用运行库的特定于多线程和DLL的版本,会将DLL和exe链接到相同的C运行时库,并因此链接一个_crtheap。分配始终与单个模块中的取消分配配对。

    这与Liunx上的行为相同吗?
    那里有什么堆?那么CRT堆呢?

    最佳答案

    我真的不知道该如何回答,但是我将尝试提供足够的常规信息,以帮助您了解需要知道的内容。

    作为unix的人,我从您的问题中学到的Windows内存管理内容是,你们经常使用“堆”这个词。除了作为“由malloc管理的内存区域”的非正式同义词外,我们没有。

    有2个主要的动态内存分配原语需要注意:brkmmap。所有其他分配函数(包括malloc)都建立在这些函数之上。
    brk是旧的。它的工作原理是,在bss段结束之后,只需将更多内存添加到进程的虚拟内存映射中即可。您向brk传递一个值,该值成为进程的“中断”地址-分配的虚拟内存的末尾。

    可以在brk之上构建malloc,方法是在每次需要更多内存时以更高的新值对其进行调用,并维护一些内部数据结构来跟踪已释放的内容和仍在使用的内容。 (经典实现中没有将内存免费释放回系统。)某些malloc实现的内部数据结构必须是heap,给brk段起了绰号:“堆”。

    另请参阅:What does brk( ) system call do?(有图片!)

    直接调用brk的程序真的很不寻常。 (甚至是薄包装sbrk)。普通程序中对brk的每次使用都是通过malloc进行的。请记住,尽管您将C库(包括malloc)视为某种可选的额外功能,但我们的操作系统与C紧密结合,因此对于内存管理等低级内容,不使用libc的程序非常有用。确实很奇怪。因此,大多数时候,brk段(也就是“堆”)中的所有内存都是由malloc管理的。但是,事实并非如此,因为...
    mmap,比brk更新(mmap来自90年代; brk来自70年代)提供了很多选择。当您想将文件映射到内存中,或者分配几个不连续的内存块,而不仅仅是在原始数据块的末尾添加一些空间时,可以使用mmap。共享库加载器使用mmap映射每个库的文本和数据。现代的malloc实现将mmap用于大型请求,将brk用于小型请求。我们还有mremap,它将映射重新定位到新的虚拟地址,同时将其保持在相同的物理地址,从而允许重新分配以避免昂贵的副本。

    如果在Linux上查看/proc/$PID/maps,则会看到一个标记为[heap]的内存区域。那是brk细分市场。每个过程中只有一个。 (我看过一些示例,其中maps文件显示了其中两个,但是它们是连续的并且具有相同的属性,因此实际上等效于单个区域。我不知道是什么原因导致重复列出。)

    考虑到所有这些背景,分配“额外堆”将意味着什么?您可以使用mmap从系统请求一些内存,从而为您提供一个独立于malloc的区域。然后,您可以对该区域进行类似malloc的管理,将其分批分发给各种大小的块,并跟踪未使用的部分。但是您的新分配器将不会成为“堆”。这实际上没有任何意义,因为系统对堆一无所知。

    07-28 01:07