Linux 如何将内存从进程返回到操作系统

Linux 如何将内存从进程返回到操作系统,linux,unix,memory,aix,sbrk,Linux,Unix,Memory,Aix,Sbrk,我对各种操作系统中的内存管理有问题 我的程序是一个服务器,它执行一些可能需要几GB内存的处理。之后,它会释放大部分内存,同时等待几个小时,直到另一个请求到达 在AIX和Solaris上,我观察到以下行为: 当我释放内存时,内存不会返回到操作系统。一个进程使用的虚拟内存量总是增加,而不是减少。物理内存也是如此,直到它的极限。因此,我们似乎也在睡眠模式下使用所有这些内存 何时可以将此内存返回操作系统?我怎样才能做到 Linux是不同的:它似乎有时确实返回内存,但我不知道何时以及如何返回。例如,我有一

我对各种操作系统中的内存管理有问题

我的程序是一个服务器,它执行一些可能需要几GB内存的处理。之后,它会释放大部分内存,同时等待几个小时,直到另一个请求到达

在AIX和Solaris上,我观察到以下行为:

当我释放内存时,内存不会返回到操作系统。一个进程使用的虚拟内存量总是增加,而不是减少。物理内存也是如此,直到它的极限。因此,我们似乎也在睡眠模式下使用所有这些内存

何时可以将此内存返回操作系统?我怎样才能做到


Linux是不同的:它似乎有时确实返回内存,但我不知道何时以及如何返回。例如,我有一个场景,在这个场景中,请求之前的进程是100MB,然后在峰值时是700MB,而在释放所有请求之后,它又降到了600MB。我不明白——如果Linux把内存还给了操作系统,为什么不是全部呢

我认为,内存分配(可能还给操作系统)的方式是在libc中。您正在使用的编程语言/库堆栈可能是原因之一

我假设glibc将返回堆顶部的非碎片内存。您的进程可能会分配它将一直使用的10MB数据。之后,将分配处理中使用的500MB数据。 在这之后,即使在处理(可能是处理的结果)之后也会保留一小部分数据。然后再分配500MB 内存布局为:

|10MB已用| 500MB处理| 1MB结果| 500MB处理|=1011MB总计

当1000MB被释放时,内存布局被激活

|10MB已使用| 500MB已释放| 1MB结果| 500MB已释放| glibc现在可能会在最后返回内存。。。 |10MB已使用| 500MB已释放| 1MB结果|=511MB“正在使用” 而且只使用了11MB

我假设情况就是这样,您需要做进一步的研究(想到单独的内存池)以确保所有内存都将被释放

我认为唯一可靠和可移植的方法是生成一个新的进程来处理您的请求。进程退出后,操作系统将获取所有相关内存

不幸的是,您在生成此流程和流程间通信方面效率低下(我注意到您正在进行大量处理-我不知道这是否意味着您的流程间通信具有相当大的数据需求)。但是,您将获得所需的内存行为。注意,如果生成相同的JVM二进制映像,操作系统不应复制实际JVM消耗的内存。

glibc库(通常用作Linux中的标准C库)可以通过两种方式分配内存-使用sbrk()或使用mmap()。它将使用mmap()进行足够大的分配

使用sbrk()分配的内存不能轻易地再次放弃(仅在特殊情况下,据我所知,glibc甚至没有尝试)。可以使用munmap()返回使用mmap()分配的内存


如果您依赖于能够将内存返回操作系统,那么可以直接使用mmap()而不是malloc();但是,如果分配大量的小块,这将变得效率低下。您可能需要在mmap()上实现自己的池分配器。

大多数情况下,在进程终止之前,内存不会返回到系统。根据操作系统和运行库的不同,内存可能会返回给系统,但我不知道有什么可靠的方法来确保这一点


如果处理需要几GB内存,请让服务器等待请求,然后生成一个新的处理数据的进程—您可以使用管道与服务器通信。处理完成后,返回结果并终止生成的进程。

您应该了解分页的工作方式。如果内存小于getpagesize(),则无法返回该内存。

+1表示mmap。我没想到。但是如果需要很多小块,我会使用一个专用的进程。
free
有时可能会通过
munmap
向内核释放内存。我认为对于足够大的内存区域,它可以做到这一点。所以问题是-如何说服glibc()调用munmap?是否有一些编译器选项,系统调用,不管什么,可以改变行为?也许会有帮助。谢谢,但是spawn对我不起作用。我正在运行C++。(我以前应该说过)我看到Java12承诺现在在某些情况下能够向操作系统返回内存-