【问题标题】:Is calloc exactly the same as malloc + memset?calloc 与 malloc + memset 完全一样吗?
【发布时间】:2013-11-14 03:01:48
【问题描述】:

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

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

【问题讨论】:

  • callocmalloc 不是内核操作,它们只是 C 库函数。
  • @Barmar True 但是“乐观内存分配策略”在哪里实施?在库还是内核中?
  • @Barmar 它们不仅仅是 C 库函数,因为它们调用系统调用。
  • @ouah:传统上,malloc() 等的底层系统调用是sbrk(),这不是 POSIX 标准系统调用。我不知道 Linux 是否对内存管理功能有实际的系统调用,但这似乎不太可能,因为您可以使用替代库进行内存分配。

标签: c linux linux-kernel glibc


【解决方案1】:

cited duplicate 或此处未提及。 Linux 使用虚拟内存,并且可以分配更多系统中物理可用的内存。 calloc() 的幼稚实现在用户空间中简单地执行 malloc() 加上 memset() 将触及每个页面。

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

这称为copy-on-write 或简称COWmalloc() 通常表现相同。对于小尺寸,the 'C' library 将使用 binning 并与其他小尺寸分配共享 4k 页面。

因此,通常涉及两层。

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

如果请求的内存大小很大并且需要为进程分配新的内存,那么上面的大部分内容都适用(通过 Linux 的进程内存管理)。但是,如果请求的内存很小,那么它就像malloc() 加上memset()。在较大的分配大小中,memset() 是破坏性的,因为它接触了内存,内核认为它需要一个新的页面来分配。

【讨论】:

【解决方案2】:

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

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

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

正如cmets中提到的this answer提供了一个很好的解释。

【讨论】:

  • @tux3,如果你在内核空间,你可以做任何事情。问题是关于malloccalloc 函数可用的用户空间。如果您可以在您的用户应用程序中从内核获取未初始化的页面,那将是一个严重的安全漏洞。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2013-11-17
      • 2013-03-06
      • 2021-02-02
      • 2014-10-04
      • 2017-05-06
      • 2012-05-28
      • 2010-10-04
      • 2012-03-02
      • 2014-10-16
      相关资源
      最近更新 更多