设置 ulimit -v 是否足以避免内存泄漏

设置 ulimit -v 是否足以避免内存泄漏

最近几周,我们有一个进程发生了一次性内存泄漏,导致它耗尽了 RHEL 7 机器上的所有内存

我们现在希望对此设置限制,以便永远不会超过一定数量

我们使用 ulimit -v 设置来设置此数量(因为 -m 设置不起作用)

因此,我想知道这是否足够,还是我们还需要一种方法来限制物理内存?如果是这样,最好的方法是什么?

如果虚拟内存总是随物理内存一起增长,那么 -v 本身就足够了

答案1

关于如何工作的一些描述ulimit

ulimit已处理setrlimitgetrlimit系统调用。通过stracebash 进程(ulimit是 的组成部分)很容易确保bash。我设置了 1024kb max memory size

$ ulimit -m 1024

在另一个控制台中:

$ strace -p <my_bash_pid>
. . .
getrlimit(RLIMIT_RSS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
setrlimit(RLIMIT_RSS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
. . . 

setrlimit手册页接下来写的是RLIMIT_RSS

RLIMIT_RSS指定进程驻留集(RAM 中驻留的虚拟页数)的限制(以页为单位)。此限制仅在以下情况下有效Linux 2.4.x,x < 30,并且只影响对 疯狂的维斯(2)指定 MADV_WILLNEED。

madvicesyscall 只是对内核的建议,内核可能会忽略此建议。甚至bash手册页也ulimit写了以下内容:

-m 最大驻留集大小(许多系统不遵守此限制)

-m这就是为什么行不通的原因。

关于-v选项:

我设置了1024 kb的虚拟内存:

$ ulimit -v 1024

在另一个控制台中:

$ strace -p <my_bash_pid>
. . .
getrlimit(RLIMIT_AS, {rlim_cur=RLIM64_INFINITY, rlim_max=RLIM64_INFINITY}) = 0
setrlimit(RLIMIT_AS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
. . .

setrlimit手册页接下来写的是RLIMIT_AS

RLIMIT_AS进程虚拟内存(地址空间)的最大大小(以字节为单位)。此限制影响调用布尔克(2),映射(2)重映射(2),超出此限制后会失败并出现错误 ENOMEM。此外,自动堆栈扩展也会失败(如果没有通过 sigaltstack(2) 提供可用的备用堆栈,则会生成 SIGSEGV 来终止进程)。由于该值是 long,因此在具有 32 位 long 的计算机上,此限制最多为 2 GiB,或者此资源是无限的。

程序由3个段(数据、代码、堆栈)组成虚拟程序存储空间。

  • 代码段是常量,包含程序指令。

  • 数据段由以下控制:

    brk系统调用调整大小数据段程序的(虚拟内存的一部分)。

    mmap系统调用将文件或设备映射到进程的虚拟内存。

    许多程序通过调用 C 库 ( ) 中的标准函数来分配内存(直接或间接),malloc该函数从(数据段的一部分)。malloc通过调用系统调用来调整数据段的大小brk

  • 堆栈存储函数变量(变量在从堆栈分配期间占用内存)。

所以,这就是为什么该-v选项适合您。

如果-v足以完成您的任务,那么就没有理由做其他事情,这就足够了。


如果您想控制进程的大量特定内存功能(内存压力、交换使用情况、RSS 限制、OOM 等),我建议您使用cgroup内存能力。

如果您的应用程序是服务我建议你使用系统切片功能,作为控制和限制cgroupssystemd.

相关内容