Linux более совершенный эвристический

В статье о пере-фиксации из документа ядра просто упоминается, что режим сверх-фиксации 0 основан на эвристической обработке сверх-фиксации. Это не обрисовывает в общих чертах эвристику, вовлеченную.

Может ли кто-то пролить свет на фактическую эвристику? Любая соответствующая ссылка на исходники ядра тоже работает!

1 ответ

На самом деле, документация ядра по учету overcommit имеет некоторые детали: https://www.kernel.org/doc/Documentation/vm/overcommit-accounting

Ядро Linux поддерживает следующие режимы обработки overcommit

0 - Эвристическая обработка overcommit.

Очевидные нарушения адресного пространства отклоняются. Используется для типичной системы. Это обеспечивает серьезное сбои при распределении, позволяя при избыточной загрузке уменьшить использование подкачки. В этом режиме root может выделить немного больше памяти. Это по умолчанию.

Также Документация / sysctl / vm.txt

overcommit_memory: это значение содержит флаг, который разрешает чрезмерное использование памяти.
Когда этот флаг равен 0, ядро ​​пытается оценить объем свободной памяти, когда пользовательское пространство запрашивает больше памяти...

См. Documentation / vm / overcommit-accounting и mm/mmap.c::__vm_enough_memory() для получения дополнительной информации.

Также, man 5 proc:

/proc/sys/vm/overcommit_memory Этот файл содержит режим учета виртуальной памяти ядра. Значения:

                0: heuristic overcommit (this is the default)
                1: always overcommit, never check
                2: always check, never overcommit

В режиме 0 вызовы mmap(2) с MAP_NORESERVE не проверяются, и проверка по умолчанию очень слабая, что приводит к риску получения процесса "OOM-kill".

Таким образом, очень большие выделения отключаются эвристикой, но иногда приложение может выделить больше виртуальной памяти, чем размер физической памяти в системе, если оно не использует все это. С MAP_NORESERVE количество mmapable памяти может быть выше.

Параметр " Политика overcommit устанавливается через sysctl` vm.overcommit_memory ' ", поэтому мы можем узнать, как это реализовано в исходном коде: http://lxr.free-electrons.com/ident?v=4.4;i=sysctl_overcommit_memory, определенный в строке 112 мм / mmap.c

  112 int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS;  /* heuristic overcommit */

и постоянный OVERCOMMIT_GUESS (определено в linux / mman.h) фактически используется только в строке 170 файла mm / mmap.c, это реализация эвристики:

138 /*
139  * Check that a process has enough memory to allocate a new virtual
140  * mapping. 0 means there is enough memory for the allocation to
141  * succeed and -ENOMEM implies there is not.
142  *
143  * We currently support three overcommit policies, which are set via the
144  * vm.overcommit_memory sysctl.  See Documentation/vm/overcommit-accounting
145  *
146  * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
147  * Additional code 2002 Jul 20 by Robert Love.
148  *
149  * cap_sys_admin is 1 if the process has admin privileges, 0 otherwise.
150  *
151  * Note this is a helper function intended to be used by LSMs which
152  * wish to use this logic.
153  */
154 int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
...
170         if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
171                 free = global_page_state(NR_FREE_PAGES);
172                 free += global_page_state(NR_FILE_PAGES);
173 
174                 /*
175                  * shmem pages shouldn't be counted as free in this
176                  * case, they can't be purged, only swapped out, and
177                  * that won't affect the overall amount of available
178                  * memory in the system.
179                  */
180                 free -= global_page_state(NR_SHMEM);
181 
182                 free += get_nr_swap_pages();
183 
184                 /*
185                  * Any slabs which are created with the
186                  * SLAB_RECLAIM_ACCOUNT flag claim to have contents
187                  * which are reclaimable, under pressure.  The dentry
188                  * cache and most inode caches should fall into this
189                  */
190                 free += global_page_state(NR_SLAB_RECLAIMABLE);
191 
192                 /*
193                  * Leave reserved pages. The pages are not for anonymous pages.
194                  */
195                 if (free <= totalreserve_pages)
196                         goto error;
197                 else
198                         free -= totalreserve_pages;
199 
200                 /*
201                  * Reserve some for root
202                  */
203                 if (!cap_sys_admin)
204                         free -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
205 
206                 if (free > pages)
207                         return 0;
208 
209                 goto error;
210         }

Итак, эвристика - это способ оценить, сколько страниц физической памяти используется сейчас (free), когда обрабатывается запрос дополнительной памяти (приложения запрашивают pages страницы).

При всегда включенном overcommit ("1") эта функция всегда возвращает 0 ("достаточно памяти для этого запроса")

164         /*
165          * Sometimes we want to use more memory than we have
166          */
167         if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
168                 return 0;

Без этой эвристики по умолчанию в режиме "2" ядро ​​будет пытаться учесть запрошенные pages страницы, чтобы получить новые Committed_AS (от /proc/meminfo):

162         vm_acct_memory(pages);
...

на самом деле это просто приращение vm_committed_as - __percpu_counter_add(&vm_committed_as, pages, vm_committed_as_batch);

212         allowed = vm_commit_limit();

Некоторая магия здесь:

401 /*
402  * Committed memory limit enforced when OVERCOMMIT_NEVER policy is used
403  */
404 unsigned long vm_commit_limit(void)
405 {
406         unsigned long allowed;
407 
408         if (sysctl_overcommit_kbytes)
409                 allowed = sysctl_overcommit_kbytes >> (PAGE_SHIFT - 10);
410         else
411                 allowed = ((totalram_pages - hugetlb_total_pages())
412                            * sysctl_overcommit_ratio / 100);
413         allowed += total_swap_pages;
414 
415         return allowed;
416 }
417 

Так, allowed устанавливается либо как килобайт в vm.overcommit_kbytes sysctl или как vm.overcommit_ratio в процентах от физической памяти, плюс размеры подкачки.

213         /*
214          * Reserve some for root
215          */
216         if (!cap_sys_admin)
217                 allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);

Разрешить некоторый объем памяти только для root (Page_shift равен 12 для здорового человека, page_shift-10 - это просто преобразование из килобайта в число страниц).

218 
219         /*
220          * Don't let a single process grow so big a user can't recover
221          */
222         if (mm) {
223                 reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
224                 allowed -= min_t(long, mm->total_vm / 32, reserve);
225         }
226 
227         if (percpu_counter_read_positive(&vm_committed_as) < allowed)
228                 return 0;

Если после учета запроса все пользовательское пространство по-прежнему имеет выделенный объем памяти меньше разрешенного, выделите его. В другом случае отклоните запрос (и отмените запрос).

229 error:
230         vm_unacct_memory(pages);
231 
232         return -ENOMEM;

Другими словами, как указано в "Ядре Linux. Некоторые замечания по ядру Linux", 2003-02-01, Andries Brouwer, 9. Memory, 9.6 Overcommit и OOM - https://www.win.tue.nl/~aeb/linux/lk/lk-9.html:

Идти в правильном направлении

Начиная с 2.5.30 значения:

  • 0 (по умолчанию): как и раньше: угадайте, насколько чрезмерное ограничение является разумным,
  • 1 никогда не отказывайся от malloc (),
  • 2: будьте точны в отношении чрезмерной передачи - никогда не фиксируйте виртуальное адресное пространство больше, чем пространство подкачки плюс дробь overcommit_ratio физической памяти.

Таким образом, "2" - это точное вычисление объема памяти, использованного после запроса, а "0" - эвристическая оценка.

Другие вопросы по тегам