Странное поведение кэша Unevictable (ядро Linux)

Странное поведение кэша Unevictable (ядро Linux)

Я наблюдаю поведение, которое не могу объяснить, на моем встраиваемом Linux-целевом устройстве (initramfs инет обмена).

Поскольку подкачки нет, я бы ожидал, что все в /tmp (tmpfs) будет помечено как невыполнимое. Вместо этого я наблюдаю следующее при использовании следующего скрипта:

#!/bin/sh
count=1
while true; do
    echo "#$count"
    dd if=/dev/zero of=/tmp/zero$count bs=1M count=10 && cat /proc/meminfo | grep 'Unevictable\|Shmem'
    count=`expr $count + 1`
    sleep 3
done
  • При записи большого количества файлов по 10 МБ Shmem растет линейно, но неизвлекаемая память очень быстро увеличивается с 0 КБ до ~200 МБ:

    #40
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.102484 seconds, 97.6MB/s
    Unevictable:           0 kB
    Shmem:            453776 kB
    #41
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.047640 seconds, 209.9MB/s
    Unevictable:           0 kB
    Shmem:            464196 kB
    #42
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.101833 seconds, 98.2MB/s
    Unevictable:         884 kB
    Shmem:            474616 kB
    #43
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.051686 seconds, 193.5MB/s
    Unevictable:      234612 kB
    Shmem:            485040 kB
    #44
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.052157 seconds, 191.7MB/s
    Unevictable:      238568 kB
    Shmem:            495572 kB
    #45
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.043332 seconds, 230.8MB/s
    Unevictable:      245332 kB
    Shmem:            505892 kB
    #46
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.042653 seconds, 234.4MB/s
    Unevictable:      245332 kB
    Shmem:            516312 kB
    #47
    10+0 records in
    10+0 records out
    10485760 bytes (10.0MB) copied, 0.048478 seconds, 206.3MB/s
    Unevictable:      248384 kB
    Shmem:            526724 kB
    
  • Если я удалю все нулевые файлы, неизгоняемая память останется на том же уровне. Означает ли это, что я потерял всю эту оперативную память? Похоже на то, что OOM killer, похоже, был вызван раньше. Как мне вернуть ее?

    # rm /tmp/zero*
    # cat /proc/meminfo | grep 'Unevictable\|Shmem'
    Unevictable:      288372 kB
    Shmem:             48412 kB
    
  • С фрагментами по 100 МБ вместо 10 МБ:

    #1
    100+0 records in
    100+0 records out
    104857600 bytes (100.0MB) copied, 0.422820 seconds, 236.5MB/s
    Unevictable:           0 kB
    Shmem:            150168 kB
    #2
    100+0 records in
    100+0 records out
    104857600 bytes (100.0MB) copied, 0.471385 seconds, 212.1MB/s
    Unevictable:           0 kB
    Shmem:            252516 kB
    #3
    100+0 records in
    100+0 records out
    104857600 bytes (100.0MB) copied, 0.444059 seconds, 225.2MB/s
    Unevictable:           0 kB
    Shmem:            354888 kB
    #4
    100+0 records in
    100+0 records out
    104857600 bytes (100.0MB) copied, 0.414981 seconds, 241.0MB/s
    Unevictable:           0 kB
    Shmem:            457368 kB
    #5
    100+0 records in
    100+0 records out
    104857600 bytes (100.0MB) copied, 5.538392 seconds, 18.1MB/s
    Unevictable:      288264 kB
    Shmem:            559700 kB
    #6
    dd: writing '/tmp/zero6': No space left on device
    

Может ли кто-нибудь объяснить наблюдаемое поведение, которое, как мне кажется, является ошибкой ядра?

Спасибо

решение1

Подозреваю, что это не tmpfs, а ramfs.

Список неисключаемых страниц охватывает следующие классы неисключаемых страниц:

  • Те, что принадлежат ramfs.

  • Они отображены в SHM_LOCKразделяемые области памяти.

  • Они сопоставлены с VM_LOCKED[mlock()ed] VMA.

Инфраструктура также может быть способна обрабатывать другие условия, которые сделают страницы неизбежными либо по определению, либо в силу обстоятельств в будущем.

https://www.kernel.org/doc/Documentation/vm/unevictable-lru.txt

В ответ на ваш вопрос,Красная Шапкарезюмировать «Неизбежный» можно так: «Объем памяти в кибибайтах,обнаружен кодом pageout, который невозможно удалить, поскольку он заблокирован в памяти пользовательскими программами».

Читая полный документ, похоже, что по какой-то причине ramfsвыделения начинаются с обычного Inactive(anon)списка LRU. Как только у вас заканчивается свободная память и вы начинаете запускать reclaim (pageout), списки сканируются, и виртуальная машина «обнаружит» заблокированную память и переместит ее в список невытесняемых.

В связи с этим, есть такжекомментарий к ядручто говорит о том, что поле «Mlocked» может не учитывать заблокированные страницы немедленно. (Возможно, в некоторых случаях это так, я не проверял).

NR_MLOCK,       /* mlock()ed pages found and moved off LRU */

Я не предполагаю, что ядро ​​сканирует весь список сразу, но предполагаю, что оно сканирует его большими пакетами.

Проблема этой теории в том, что я не знаю, почему/как ваше ядро ​​будет сканировать списки "anon", если у вас не настроена подкачка. Я даже нашелкод-

/* If we have no swap space, do not bother scanning anon pages. */
if (!sc->may_swap || mem_cgroup_get_nr_swap_pages(memcg) <= 0) {
    scan_balance = SCAN_FILE;
    goto out;
}

Связанный контент