内存分配是系统调用吗?

61

内存分配是系统调用吗?例如,mallocnew。堆是否由不同的进程共享并由操作系统管理?私有堆又如何呢?如果堆中的内存分配由操作系统管理,那么这会有多大的开销?

我还想获取一些关于此主题的更多阅读链接。

4个回答

63
一般情况下,mallocnew 每次调用并不会执行系统调用。但是,它们使用一种更底层的机制来分配大块内存。在 Windows 上,这个底层机制是 VirtualAlloc()。我认为在 POSIX 系统上,这与 mmap() 有些类似。这两者都会执行一个系统调用,在操作系统级别上为进程分配内存。随后的分配将使用这些大页面的较小部分,而不会产生系统调用。
堆通常是内部进程的,不与进程共享。如果您需要这样做,大多数操作系统都有用于分配共享内存的 API。这些 API 的便携式封装可在 Boost.Interprocess 库中找到。
如果您想了解更多关于内存分配及其与操作系统的关系,可以参考一本好的操作系统书籍。我总是建议阅读 Andrew S. Tanenbaum 的 《现代操作系统》,因为它非常易于理解。

13
在Linux系统中,brk(2)sbrk(2)mmap(2)一起用于内存分配。我还想提一下,Knuth的《计算机程序设计艺术》第一卷也是关于内存分配方面的很好的参考资料。 - jmbr
4
这取决于运行时环境。使用Visual Studio 2010发行版库时,malloc和free调用HapAlloc / HeapFree直接进行操作,因此每个分配都有一个系统调用。然后,堆函数使用VirtualAlloc。 - Suma
3
@Suma:HeapAlloc不是系统调用,也不一定执行任何系统调用。 - user541686
@Mehrdad HeapAlloc 在 kernel32.dll 中定义,如果这不是系统,那还有什么是系统呢? - Suma
5
@Suma: "系统调用"并不是被定义为"在kernel32中定义"。更准确地说,系统调用是指调用syscallsysenter指令的东西。这些指令位于ntdll.dll中,而不是kernel32.dll。它们在以NtZw开头的函数中,而不是Rtl。实际上,HeapAlloc调用RtlAllocateHeap,后者不一定执行任何系统调用。 - user541686
显示剩余2条评论

26

(假设操作系统带有内存保护。嵌入式设备可能不具备这个功能。)

内存分配是系统调用吗?

不一定是每次分配都需要进行系统调用。只有当进程的堆空间不足以满足请求的内存时,才需要调用内核进行申请。但是C库通常会请求更大的内存块,以降低系统调用的次数。

堆内存由操作系统管理,是否被多个进程共享?私有堆内存呢?

堆内存不会在多个进程之间共享,但是在多个线程之间共享。

内核内存分配的开销完全取决于操作系统。因为这是一个非常常见的事情,在正常情况下您可以期望它是高效的。在内存较低的情况下,情况会变得复杂。


21

查看 Win32 的分层内存管理。

enter image description here

内存分配总是一个系统调用,但分配是按页面进行的。如果已经有可用空间在已提交页面中,则内存管理器将分配所请求的空间而不更改内核模式。HeapAlloc 最好的一点是,它提供对分配具有精细控制的能力,而 VirtualAlloc 则会将分配舍入为单个页面,这可能导致过度使用内存。

基本上,默认堆和私有堆被视为相同,除了默认堆大小在链接时指定。默认堆大小为 1 MB,并根据需要增长。


6
"内存分配总是一个系统调用",这意味着每次调用 malloc() 都会导致一个系统调用(转换到内核模式),但这是完全不正确的。 - Jonathon Reinhart

7

内存分配函数和语言语句,例如malloc/free和new/delete,并不是系统调用。Malloc/free是C/C++库的一部分,而new/delete是C++运行时系统的一部分。它们的调用有时可能会导致系统调用。在其他语言中,内存分配也以类似的方式实现。

一般来说,内存管理无法完全脱离操作系统进行实现,因为内存是主要的系统资源之一,全局内存管理由操作系统内核完成。但由于系统调用比较昂贵,人们尝试设计语言和内存分配库,以最小化系统调用数量。

据我所知,堆是一个进程内实体。这意味着所有的内存分配/释放请求都完全由进程自身管理。操作系统只知道堆的位置和大小,并处理来自进程内存管理系统的两种类型的请求:

add memory page at virtual address X
release memory page from virtual address X

本地内存管理系统在决定堆内存池中没有足够内存或拥有过多内存时,会请求这些服务。尽管通常设计内存分配以最小化系统调用的数量,但与栈上内存分配相比,它仍然要昂贵大约一个数量级。这是因为堆内存的内存分配/释放算法比栈的更加复杂和昂贵。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接