Назад | Перейти на главную страницу

Почему в Linux (CentOS 7.2) ulimit -m не ограничивает использование памяти?

Я установил ulimit -m 1000000 для моей оболочки, затем запустил процесс, который потребляет кучу памяти (простой скрипт python из https://unix.stackexchange.com/questions/99334/how-to-fill-90-of-the-free-memory). Я говорю своему скрипту python использовать 2 ГБ памяти, и, похоже, он это делает (этот вывод htop):

    Mem[|||||||||||||||||||||||||||||||||1742/1839MB]     Uptime: 137 days(!), 16:56:32
    Swp[|||||||||||||                     591/2047MB]

  PID  USER   PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command               
  6207 mikes  20   0  2123M 1625M   156 S  0.0 88.3  0:08.77 python ./consume_memory 2000

... Посмотрите на столбец «RES» и график «MEM» выше.

ulimit -a показывает:

max memory size         (kbytes, -m) 1000000

... Почему мой процесс не запустился? Если я установлю размер виртуальной памяти с помощью ulimit -v 1500000, например, мой процесс не работает, как ожидалось:

$ ./consume_memory 900
Traceback (most recent call last):
  File "./consume_memory", line 14, in <module>
    data = megabyte * count
MemoryError

Системные характеристики:

CentOS Linux release 7.2.1511 (Core) 
Linux hostname 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)

В bash, если мы сделаем command -V ulimit мы нашли ulimit is a shell builtin, так что мы можем сделать help ulimit что говорит

 -m        the maximum resident set size

поэтому мы устанавливаем RSS. Чтобы увидеть, какой системный вызов bash на самом деле использует, мы можем попробовать

$ strace bash -c 'ulimit -m 10000'
setrlimit(RLIMIT_RSS, {rlim_cur=10000*1024, rlim_max=10000*1024}) = 0

а затем посмотреть в man setrlimit который

RLIMIT_RSS. Задает предел (в страницах) резидентного набора процесса (количество виртуальных страниц, находящихся в ОЗУ). Это ограничение действует только в Linux 2.4.x, x <30, и влияет только на вызовы madvise (2) с указанием MADV_WILLNEED.

Похоже, что в наши дни это не действует в Linux.