全部產品
Search
文件中心

Alibaba Cloud Linux:如何排查slab_unreclaimable記憶體佔用高的原因?

更新時間:Jul 17, 2024

slab_unreclaimable是指在Linux記憶體管理中由slab分配器分配的且被標記為不可回收(unreclaimable)的記憶體。當不可回收記憶體佔用總記憶體的比例過高時,將會影響可用記憶體與系統效能。本文介紹如何排查Alibaba Cloud Linux系統slab_unreclaimable記憶體佔用高的原因。

問題現象

在Linux執行個體內運行cat /proc/meminfo | grep "SUnreclaim"命令查看SUnreclaim參數指標時,發現記憶體較大(例如SUnreclaim: 6069340 kB),當該記憶體超過系統總記憶體大小的10%時,表示slab_unreclaimable記憶體佔用過高,系統可能會存在slab記憶體泄露。

可能原因

在Linux記憶體管理中,slab記憶體是核心用於高效分配小塊記憶體的一種緩衝機制。核心組件或驅動程式通過調用記憶體配置介面(kmalloc等)向slab分配器申請記憶體,但是核心組件或驅動程式又沒有正確釋放記憶體,這將導致不可用記憶體越來越多,可用記憶體越來越少。

排查步驟

  1. 遠端連線待排查問題的Linux執行個體。

    具體操作,請參見串連方式概述

  2. 運行以下命令,排查使用objects或記憶體較多,且記憶體不可回收的slab記憶體對應的名稱。

    1. 查看使用objects或記憶體最多的slab記憶體資訊。

      slabtop -s -a

      命令列返回結果中,您可以查看並記錄OBJ/SLAB列數值較高的slab記憶體對應的名稱(NAME列)。

    2. 確認slab記憶體是否為不可回收。

      命令中的<slab NAME>變數需要手動修改為上一步中擷取到的OBJ/SLAB列數值較高的slab記憶體對應的名稱。

      cat /sys/kernel/slab/<slab NAME>/reclaim_account

      例如,查看名稱為kmalloc-192的slab記憶體是否為不可回收。

      cat /sys/kernel/slab/kmalloc-192/reclaim_account

      查詢結果為0時,表示slab記憶體不可回收;查詢結果為1時,表示slab記憶體可回收。

  3. 排查slab_unreclaimable記憶體佔用高的原因。

    您可以使用crash工具進行靜態分析,也可以使用perf工具進行動態分析,排查造成slab記憶體泄露的原因。本文提供的樣本情境中,存在slab泄露的記憶體名稱為kmalloc-192

    crash工具靜態分析

    1. 運行以下命令,安裝crash工具。

      sudo yum install crash -y
    2. 運行以下命令,安裝核心調試工具kernel-debuginfo。

      • Alibaba Cloud Linux 3

        sudo yum install -y kernel-debuginfo-<核心版本> --enablerepo=alinux3-plus-debug
        說明

        核心版本需替換為系統實際的核心版本,通過uname -r命令查詢。

      • Alibaba Cloud Linux 2

        sudo yum install kernel-debuginfo -y
    3. 運行以下命令,啟動crash工具。

      sudo crash
    4. 在crash工具內,運行以下命令,查看kmalloc-192記憶體統計資訊。

      kmem -S kmalloc-192

      記憶體統計資訊較多時,您可以設定只顯示最後幾行(例如10行)資訊。

      kmem -S kmalloc-192 | tail -n 10

      命令列的返回結果樣本如下:

          SLAB              MEMORY            NODE  TOTAL  ALLOCATED  FREE
        ffffea004c94e780  ffff88132539e000     0     42         29    13
        ffffea004cbef900  ffff88132fbe4000     0     42         40     2
        ffffea000a0e6280  ffff88028398a000     0     42         40     2
        ffffea004bfa8000  ffff8812fea00000     0     42         41     1
        ffffea006842b380  ffff881a10ace000     0     42         41     1
        ffffea0009e7dc80  ffff880279f72000     0     42         34     8
        ffffea004e67ae80  ffff881399eba000     0     42         40     2
        ffffea00b18d6f80  ffff882c635be000     0     42         42     0

      ffff88028398a000統計資訊為例,空閑記憶體較少(FREE列),已指派的記憶體較多(ALLOCATED列)。

    5. 在crash工具內,運行以下命令,查看ffff88028398a000記憶體資訊。

      rd ffff88028398a000 512 -S

      命令列的返回資訊較長,您可以根據命令列提示列印多個頁面資料進行分析。例如:

      返回資訊中多次出現put_cred_rcu函數時,您可以自行查看Linux核心源碼,搜尋put_cred_rcu函數。

      void __put_cred(struct cred *cred)
      {
          call_rcu(&cred->rcu, put_cred_rcu);
      }

      查看到put_cred_rcu函數用於非同步釋放cred,且put_cred_rcu出現在cred的末尾,表示是核心中cred結構體出現了slab記憶體泄露。

    perf工具動態分析

    1. 運行以下命令,安裝perf工具。

      sudo yum install perf -y
    2. 運行以下命令,使用perf工具動態擷取kmalloc-192中沒有釋放的記憶體,動態擷取資料的時間間隔為200秒。

      sudo perf record -a -e kmem:kmalloc --filter 'bytes_alloc == 192' -e kmem:kfree --filter ' ptr != 0' sleep 200
    3. 在目前的目錄下,將動態擷取的資料列印至臨時檔案中。

      本樣本中,臨時檔案名稱為testperf.txt

      sudo perf script > testperf.txt
    4. 運行以下命令,查看testperf.txt檔案內容。

      cat testperf.txt

      您需要手動排查沒有空閑記憶體(free)的記憶體資訊,然後在Linux核心原始碼中手動查詢產生slab記憶體泄露的函數。

  4. 通過crash和perf等工具確定了記憶體泄露的函數調用路徑或者影響的核心資料結構後,建議在核心開發人員或專業營運人員指導下確定記憶體泄露的具體源頭,然後解決記憶體泄露問題。

    以下是可能用到的一些解決方案,供您參考:

    • 升級核心或補丁

    • 調整核心參數

    • 重啟影響的服務或模組

    • 最佳化應用程式或驅動

    • 重啟系統

相關文檔

slab記憶體泄露會導致執行個體上啟動並執行業務可用記憶體變少、記憶體片段化,還會引起系統OOM Killer以及系統效能抖動等問題。