共享库和可执行文件与 Linux 上的静态 C 运行时链接.它们中的每一个都有像Windows这样的独立堆吗?

Shared Libraries and Executable linking with static C run time on Linux. Does each of them have separate heap like Windows?

本文关键字:Windows 每一个 独立 Linux 可执行文件 静态 共享 链接 运行时      更新时间:2023-10-16

我很清楚窗口堆分配和堆堆栈等。虽然是 Linux 的新手,但我不太清楚它是如何工作的?

在视窗上:

  1. 在进程开始时,OS 会创建一个名为"进程堆"的默认堆。进程堆用于在没有使用其他堆的情况下分配块。
  2. 语言运行时还可以在进程中创建单独的堆。(例如,C 运行时创建自己的堆。
  3. 除了这些专用堆之外,应用程序或许多加载的动态链接库 (DLL) 之一可以创建和使用单独的堆,称为专用堆
  4. 这些堆位于所有虚拟内存系统中操作系统的虚拟内存管理器之上。
  5. a) C/C++ 运行时 (CRT) 分配器:提供 malloc() 和 free() 以及 new 和 delete 运算符。b) CRT 为其所有分配创建这样一个额外的堆(此 CRT 堆的句柄存储在 CRT 库内部名为 _crtheap 的全局变量中),作为其初始化的一部分。c) CRT 创建自己的专用堆,该堆驻留在 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传递一个值,它就成为进程的"中断"地址 - 分配的虚拟内存的末尾。

Malloc 可以构建在brk之上,方法是在每次需要更多内存时用新的、更高的值调用它,并维护一些内部数据结构来跟踪已释放的内容和仍在使用的内容。(在经典实现中没有免费将内存返回给系统。某些 malloc 实现的内部数据结构一定是一个堆,给 brk 段起了昵称:"堆"。

另请参阅:brk( ) 系统调用有什么作用?(它有图片!

程序直接调用brk真的很不寻常。(甚至是薄包装纸sbrk)。在正常程序中每次使用brk都是通过malloc 。请记住,虽然您将 C 库(包括 malloc)视为某种可选的附加功能,但我们有一个与 C 紧密耦合的操作系统,因此不使用 libc 进行内存管理等低级操作的程序确实非常奇怪。所以大多数时候,brk段(又名"堆")中的所有内存都由malloc管理。但是,反之则不然,因为...

mmap,比brk更新(mmap来自90年代;brk来自70年代)提供了很多选择。如果要将文件映射到内存中,或分配多个不连续的内存块,而不仅仅是在原始数据块的末尾添加一些空间,请使用 mmap 。共享库加载程序使用 mmap 映射每个库的文本和数据。现代malloc实现将mmap用于大型请求,将brk用于小型请求。我们还有mremap,它将映射重新定位到新的虚拟地址,同时将其保留在同一物理地址上,从而使 realloc 能够避免昂贵的副本。

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

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