【问题标题】:What are the Windows and Linux native OS/system calls made from malloc()?从 malloc() 进行的 Windows 和 Linux 本机操作系统/系统调用是什么?
【发布时间】:2013-08-04 16:55:50
【问题描述】:

我最近看到以下帖子:

内存分配器的级别不低于 malloc。 (默认 分配器通常直接或间接调用 malloc)

分配器只允许您指定不同的分配 策略。例如,您可以使用调用 malloc 的分配器 一次检索一个大的内存池,然后用于后续 分配请求,它只返回这个池的一小块。

或者你可以将它用作一个钩子来允许你执行一些额外的操作 每次分配或释放内存时的任务。

关于你的第二个问题,malloc 是你可以不用的最低的 失去便携性。 ma​​lloc 通常使用一些实现 操作系统特定的内存分配函数,这样会比较低级 仍然。但这与您的主要问题无关,因为 C++ 分配器是更高级别的抽象。

来自:C++: Memory allocators

我的问题是 - malloc 在以下操作系统中是如何实现的?

  • 适用于 Windows
  • 适用于 Linux

malloc() 调用/实现的特定于操作系统的函数是什么?

【问题讨论】:

  • 对于 Linux,它是 sbrk
  • 标准库的哪个实现? new / malloc 不一定是 OS API 本身的一部分,例如在 Windows 上,只有 HeapAllocVirtualAlloc 等作为其 API 的一部分。
  • 不,sbrk 在 Linux 上几乎已经过时,它正在使用 mmap
  • 您可以使用使用静态数组的固定大小池来提供mallocnew 的实现。目前的答案是指它是如何为最流行的标准库实现完成的。我想说这个问题没有很好地表述。
  • malloc 是一个内存分配器。它通常构建在虚拟内存空间管理原语之上(mmap 在许多 Posix 系统上)。

标签: c++ c linux windows performance


【解决方案1】:

我的问题是 - malloc 在以下操作系统中是如何实现的?

在 Linux 上有两个著名的 malloc 实现:

dlmalloc(Doug Lea 的 malloc)

ptmalloc

在 glibc、eglibc 或 newlib 等 Linux libc 上实现 ptmalloc 或 ptmalloc 的变体。

malloc() 调用/实现的特定于操作系统的函数是什么?

在 Unix 和 Linux 系统上使用 sbrkmmap 系统调用。请参阅man 2 sbrkman 2 mmap 了解更多信息。

【讨论】:

  • mmap 比已过时的sbrk 更常用(即不支持多线程)。
【解决方案2】:

好吧,我对 Linux 不太了解,但说到 windows...

内存可以分为两类。

1) 堆(进程堆、自定义创建的堆)参见 -> http://msdn.microsoft.com/en-us/library/windows/desktop/aa366711(v=vs.85).aspx 使用 HeapAlloc 和 HeapFree 等函数。当您想在默认进程堆中分配时,LocalAlloc 和 LocalFree 可以用作 HeapAlloc 的“快捷方式”。

2) 虚拟内存(由于安全性全局虚拟内存中的访问限制,通常只针对特定进程),使用VirtualAlloc、VirtualFree。见->http://msdn.microsoft.com/en-us/library/windows/desktop/aa366916(v=vs.85).aspx

据我所知,malloc 会在 windows 上使用堆分配函数。

我希望这会有所帮助。

【讨论】:

  • "从 16 位代码移植支持全局和局部函数" from here -> 不要使用LocalAlloc
  • 使用Heap* 函数分配的内存对于进程来说也是“本地的”。 IMO,您的回答表明堆和虚拟内存是两个独立的事物-它们不是。堆使用“虚拟内存”,即虚拟地址空间和物理内存。 Virtual* 函数也是如此,它们不仅仅处理虚拟地址空间。
  • @DyP 第一条评论是对的:不要再使用LocalAlloc,那是16位Windows的遗迹。始终使用HeapAlloc。但第二部分并不完全正确。令人困惑的是,即使在 Win32 中,本地堆和全局堆也是两个略有不同的东西。从一个分配的内存不能在另一个上释放。因此,尽管您是正确的,它们在语义上相似并且对于流程都是“本地的”,但它们并不相同。
  • 另外,直接调用VirtualAlloc 没有什么意义,因为HeapAlloc 会在必要时为您服务。唯一应该直接调用VirtualAlloc 的情况是,如果您正在做一些真正 低级内存管理工作并且需要它提供的额外选项。
  • @CodyGray 我没有谈论全局和本地堆,你指的是什么?我所说的“本地”是指VirtualAllocHeapAlloc 的每个内存分配都是特定于进程的。
【解决方案3】:

在 Windows 中,在 MSVC 的最新版本中,malloc(和 C++ new,因为它使用与 new 的实际内存分配部分相同的基础实现)调用 HeapAlloc()。在其他版本中,例如 g++ mingw,C 运行时是较旧的版本,它不会直接调用 HeapAlloc,但在它的基础上,它仍然会转到 HeapAlloc - 找到不同的东西,我们需要回到 95 之前的 Windows,它确实有一组 GlobalAllocLocalAlloc 函数 - 但我认为现在人们不使用 16 位编译器 - 至少不是用于 Windows 编程。

在 Linux 中,如果您使用glibc,则取决于分配的大小是否调用sbrkmmap - mmap(在标志中带有MAP_ANONYMOUS)用于更大的分配(超过阈值,我认为在典型实现中为 2MB)

【讨论】:

  • “在 Windows 中,在最近的版本中”-> Windows 的标准库(C 和 C++)的所有实现都使用它吗? (我知道 MSVC 有)
  • 因为 G++(mingw - 不确定 Cygwin 是如何工作的)使用 MSVC(虽然是旧版本,它可能不会直接映射到 HeapAlloc),是的。我不知道有任何 C 或 C++ 库使用除 HeapAlloc 之外的任何东西来实际从 Windows 获取内存块——除非我们回溯到它使用 LocalAllocGlobalAlloc,但我们正在谈论16 位窗口。
  • 我们的项目在 Windows 上将 ptmalloc() 和 dlmalloc() 与 MSVC 结合使用,使用 VirtualAlloc() 模拟 sbrk()。
  • mmap 页面似乎是指将设备映射到内存而不是动态分配内存?
  • @user997112:取决于你传入的标志,更多的是关于将文件映射到内存中。但是使用MAP_ANYNOMOUS(以及正确传递其他参数,如链接中所述),它只是为进程提供了一块内存。
【解决方案4】:

malloc() 和朋友被认为是编译器附带的运行时系统的一部分。所以每个编译器都可以并且确实使用不同的操作系统调用来实现 malloc。

正如其他人所说,在 Linux 上,选项是 sbrk() 和 mmap()。

在 Windows 上,选项是 HeapAlloc() 和 VirtualAlloc()。

【讨论】:

    【解决方案5】:

    在 Windows 上,malloc 实现通常会调用 win32 堆函数,例如 HeapCreateHeapDestroyHeapAllocHeapFree。这些函数将调用位于 ntdll.dll 中的 NTDLL 用户模式堆管理器,这些函数将具有 RtlxxxHeap 名称、RtlAllocateHeapRtlCreateHeap 等...

    最终将调用NtxxxVirtualMemory 组内的系统调用NtAllocateVirtualMemoryNtQueryVirtualMemoryNtFreeVirtualMemory

    【讨论】:

      猜你喜欢
      • 2011-11-17
      • 2017-11-25
      • 1970-01-01
      • 2020-08-12
      • 2021-06-02
      • 1970-01-01
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多