【问题标题】:free() not freeing memory in embedded linux.free() 不释放嵌入式 linux 中的内存。
【发布时间】:2014-01-29 14:28:19
【问题描述】:

我在嵌入式 Linux 中使用 malloc() 分配了内存(大约 10 MB)。并检查了可用内存为 67080 kB,但即使使用 free() 释放它,它仍然保持不变。只有在应用程序终止后,内存才能再次可用。 free() 是否不会使释放的内存对系统可用,如果是如何使其可用。

【问题讨论】:

  • 这取决于 malloc 的实现,但通常会有一个内部池,因此您可能看不到释放指针的任何立竿见影的效果。
  • 当您free 内存时,系统仍会为您保留它,以防您需要再次分配它(因此它不必重做内存映射表)。系统会在需要时占用内存。
  • 请注意,如果您正在运行一种(越来越常见的)uClinux 或其他非 MMU 嵌入式 Linux 配置,则将内存返回到系统变得更加困难。
  • @Chris:是的,我正在使用嵌入式 Linux(类似于 uClinux 的定制版本)。

标签: c free embedded-linux


【解决方案1】:

free 是一个 libc 库调用。它将堆空间标记为可重用。它不保证关联的虚拟映射将被释放。只有在您的操作系统释放脏虚拟映射后,该内存才会再次在系统范围内释放。这只会发生在页面块中。

此外,如果您使用 malloc 和家人分配内存并且没有使用它,那么在此之前它实际上并没有消耗物理内存 - 所以释放它不会有任何作用。

【讨论】:

  • 谢谢。我需要其他信息。有什么方法可以让系统在应用程序中使用释放的内存?
  • @Satchit 只有系统调用可以做到这一点。为此,您需要手动使用mmap/munmap 管理内存分配。 madvise/MAP_DONTNEED 也可以在有效映射上执行此操作。请注意,这些系统调用仅适用于系统页面块中的分配。检查sysconf(SC_PAGESIZE) 的系统页面大小。
  • 我这样使用它 int* mem = (int*)mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0); retval = munmap(mem, 40960);我的页面大小是 4096 字节。但仍然没有释放。我应该以不同的方式使用 mmap 吗?
  • @Satchit 你真的把那个内存分页了吗?如果您 mmap 内存,但不使用它,那么它也不会消耗任何 RAM。在每一页上写一些东西以使它们变脏。或者将MAP_POPULATE 传递给mmap,但这在不同的操作系统上具有不同的行为。
  • 我已经使用了内存,只是用一些值初始化它。实际上我正在使用 cat /proc/meminfo 来查看可用空间。
【解决方案2】:

free() 是否不会使释放的内存可供系统使用。

不,通常不会。 malloc() 通常通过低级别的sbrk()mmap() 调用向操作系统请求内存。一旦分配给应用程序,free() 只是将内存返回到属于应用程序的内存池。也就是说,它不会返回给操作系统以供其他进程使用。 (尽管在某些情况下有一些启发式方法可以这样做)。

如果有交换空间,问题就不会那么严重了,操作系统将换出应用程序未使用的内存,为所需的额外物理内存腾出空间。

如果是,如何使其可用。

退出应用程序。

或者您需要编写自己的内存分配器来执行此操作。(在一般情况下,这不是一件容易的事,特别是如果您不想牺牲开销和速度)。

对于一个相对较大的 10MB 单块,您可以简单地使用 mmap() 请求匿名内存,当您 munmap() 那块内存时,内存将被释放回操作系统。

【讨论】:

  • 我这样使用它 int* mem = (int*)mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0); retval = munmap(mem, 40960);仍然没有被释放到系统..请提出建议。
  • @Satchit 在这里当然可以,虽然不需要 MAP_SHARED,但请使用 MAP_PRIVATE。但是,您将很难确定 40kb 是否已返回给操作系统,它只需要几次库调用,然后您的进程可能突然映射了更多内存(例如写入标准输出),并且整体内存统计信息会波动超过 40kb。你如何确定它不起作用?尝试使用您提到的 10Mb。确保检查 munmap() 是否成功。
【解决方案3】:

取自 malloc 3 手册页:

通常,malloc() 从堆中分配内存,并调整 使用 sbrk(2) 根据需要设置堆的大小。分配块时 大于 MMAP_THRESHOLD 字节的内存,glibc malloc() 实现将内存分配为私有匿名映射 使用 mmap(2)。 MMAP_THRESHOLD 默认为 128 kB,但 使用 mallopt(3) 进行调整

您可以尝试修改 MMAP_THRESHOLD,以便通过使用 malloc 调用 mmap。如果你这样做,free 保证通过 mmap 分配的内存将在你释放后立即返回给系统。

【讨论】:

  • 即使我使用了 40 KB 的内存,它仍然没有释放给系统。
  • 虽然不一定与观察到的解除分配行为相关,但值得注意的是嵌入式系统不一定使用 glibc,较小的替代方案可能具有或可能不具有类似的分配行为。
【解决方案4】:

您的 malloc() 调用从系统获取内存,并维护一个堆数据结构以跟踪进程中已使用和空闲的内存。您的 free() 调用将内存返回到堆中,在那里它们被标记为空闲,但它们仍然是进程内存的一部分。

如果您希望内存释放以将页面返回给系统,则必须编写自己的内存管理器,但请记住,它只能在正确的条件下完全释放内存:这取决于您的应用程序的行为,您的分配和解除分配是否跨越页面边界和干净地碎片整理等。您需要了解应用程序的内存分配行为以了解这是否有任何好处。

【讨论】:

    猜你喜欢
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    • 2011-05-31
    • 1970-01-01
    相关资源
    最近更新 更多