常驻集大小(RSS)限制无效

20 投票
4 回答
15355 浏览
提问于 2025-04-15 23:59

在一台运行Ubuntu 10.04系统、内核版本为2.6.32-22-generic的机器上,出现了以下问题:给一个进程设置内存使用限制(也就是居民集大小,简称RSS)似乎没有任何效果。我现在在Python中用以下代码来设置这个限制:

import resource
# (100, 100) is the (soft, hard) limit. ~100kb.
resource.setrlimit(resource.RLIMIT_RSS, (100, 100))
memory_sink = ['a']*10000000   # this should fail

每次运行这个代码时,列表memory_sink都能成功。但是当我用top命令查看RSS使用情况时,我发现这个进程可以轻松使用到1GB的内存,这就说明限制没有生效。那么,RSS限制在这个内核或这个系统上就不管用吗?顺便提一下,resource.RLIMIT_NPROC(用户进程限制)是有效的。

4 个回答

4

一个相关的限制是虚拟内存或地址空间(RLIMIT_AS),这个限制是有效的。它可以在不使用外部工具的情况下,限制Python进程及其子进程的内存使用。

>>> size = 50*1024*1024 # In bytes
>>> resource.setrlimit(resource.RLIMIT_AS, (size, resource.RLIM_INFINITY))
>>> a = 'a' * size
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError

来自手册页面的内容:

RLIMIT_AS。进程的虚拟内存(地址空间)的最大大小,以字节为单位。

这里有一个很好的解释,说明了常驻集(Resident Set)和虚拟内存大小(VM size)之间的区别 - 在Linux内存管理中,RSS和VSZ是什么

19

你可以通过使用cgroups来实现这个功能。详细的内容可以在我的博客上找到,但简单来说(在Ubuntu 11.04上测试过)就是:

  • 安装cgroup-bin这个软件包。

  • 编辑/etc/cgconfig.config文件,创建一个内存限制的组。例如,我添加了:

    group limited {
      memory {
        memory.limit_in_bytes = 50M;
      }
    }
    
  • 运行

    $ sudo restart cgconfig
    $ sudo chown -R jlebar /sys/fs/cgroup/memory/limited
    $ cgexec -g memory:limited your/program
    

我观察到我的程序在要求只使用50M内存时,实际使用了93M的RSS,这对我来说没问题,因为我的目标只是让程序进行分页。

cgclassify可以让你对正在运行的进程施加限制。需要注意的是,对于RSS,这个限制只适用于限制生效后分配的内存。

18

来自 getrlimit 的手册页面:

RLIMIT_RSS
Specifies the limit (in pages) of  the  process's  resident  set
(the  number of virtual pages resident in RAM).  This limit only
has effect in Linux 2.4.x, x < 30, and there only affects  calls
to madvise(2) specifying MADV_WILLNEED.

看起来在 Linux 内核 2.6 上,这个功能是不支持的。

撰写回答