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
  • 10MB のファイルを多数書き込む場合、Shmem は直線的に増加しますが、回避不可能なメモリは 0KB から約 200MB に急速に増加します。

    #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
    
  • ゼロ ファイルをすべて削除しても、排除不可能なメモリは同じレベルのままです。これは、すべての RAM を失ったことを意味しますか? OOM キラーが以前に呼び出されたように見えるため、そのように見えます。どうすれば回復できますか?

    # rm /tmp/zero*
    # cat /proc/meminfo | grep 'Unevictable\|Shmem'
    Unevictable:      288372 kB
    Shmem:             48412 kB
    
  • 10MB ではなく 100MB のチャンクの場合:

    #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() された] VMAにマップされます。

将来的には、インフラストラクチャは、定義上または状況によってページを退避不可能にするその他の条件にも対処できるようになる可能性があります。

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

あなたの質問に対する答えは、レッドハット「Unevictable」を「メモリの量(キビバイト単位)ページアウトコードによって発見されたこれは、ユーザー プログラムによってメモリにロックされているため、削除できません。」

ramfs完全なドキュメントを読むと、何らかの理由で割り当てが通常の LRU リストから始まるようですInactive(anon)。空きメモリが不足して再利用 (ページアウト) をトリガーし始めると、リストがスキャンされ、VM はロックされたメモリを「検出」して、それを排除不可能なリストに移動します。

関連して、カーネルコメントこれは、「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;
}

関連情報