1

在 linux 中,calloc 与 malloc + memset 完全相同还是取决于确切的 linux/内核版本?

我对你是否可以分配比你实际拥有的更多 RAM 的问题特别感兴趣(因为你当然可以分配比你实际拥有的更多的 RAM,你只是不能写入它)。换句话说,calloc 是否总是按照规范建议的那样实际写入您已分配的内存。

4

4 回答 4

5

当然,这取决于实现,但在现代 Linux 上,您可能可以。最简单的方法是尝试一下,但我是根据以下逻辑说的。

您可以malloc超过您拥有的内存(物理+虚拟),因为内核会延迟您的内存分配,直到您实际使用它。我相信这是为了增加您的程序不会因内存限制而失败的机会,但这不是问题所在。

calloc相同,malloc但零初始化内存。当您向 Linux 请求一页内存时,Linux 已经对其进行了零初始化。因此,如果calloc可以知道它所请求的内存只是从内核请求的,它实际上不必将其初始化为零!由于它没有,因此无法访问该内存,因此它应该能够请求比实际更多的内存。

正如评论中提到的,这个答案提供了一个很好的解释。

于 2013-11-03T10:04:43.050 回答
2

是否calloc需要写入内存取决于它是从已分配给进程的堆页中获得分配,还是必须请求内核为进程分配更多内存(使用系统调用,例如sbrk()or mmap())。当内核为进程分配新内存时,它总是先将其清零(通常使用 VM 优化,因此它实际上不必写入页面)。但是,如果它正在重用之前分配的内存,则必须将memset()其归零。

于 2013-11-03T10:07:01.913 回答
1

引用的副本或此处未提及。Linux 使用虚拟内存,可以分配系统中物理可用的更多内存。一个简单的实现calloc()只是在用户空间中做一个malloc()加号memset()将触及每一页。

由于 Linux 通常以 4k 块分配,所有calloc()块都是相同的,并且最初读取为零。也就是说同一个4k内存块可以只读映射而整个calloc()空间只占用大约size/4k * pointer_size + 4k。当程序写入calloc()空间时,会发生页面错误,Linux 将分配一个新页面(4k)并恢复程序。

这称为写时复制或简称COWmalloc()通常会以相同的方式表现。对于小尺寸,“C”库将使用分箱并与其他小尺寸分配共享 4k 页。

因此,通常涉及两层。

  1. Linux 内核的进程内存管理。
  2. glibc堆管理。

如果请求的内存大小很大并且需要为进程分配新的内存,那么上面的大部分内容都适用(通过 Linux 的进程内存管理)。但是,如果请求的内存很小,那将是一个malloc()加号memset()。在大的分配大小中,memset()由于它触及内存并且内核认为它需要一个新的页面来分配,所以它是有害的。

于 2013-11-04T17:14:36.807 回答
0

malloc(3)的内存不能超过内核为执行malloc(3)-ing 的进程提供的内存。malloc(3)如果您无法分配要分配的内存量,则返回 NULL。此外,malloc(3)memset(3)由您的 c 库 ( libc.so) 定义,而不是您的内核。Linux 内核定义了mmap(2)和其他低级内存分配函数,而不是*alloc(3)家族(不包括kalloc())。

于 2013-11-03T10:01:17.897 回答