KFENCE (Kernel Electric-Fence), çekirdek kodundaki ve modüllerdeki bellek bozulmalarını tespit eden ve ayrıntılı hata raporları oluşturan düşük ek yükli bir Linux çekirdek aracıdır.
Alibaba Cloud Linux 3, KFENCE'i hem üretim hem de çevrimdışı kullanım için dinamik olarak etkinleştirme/devre dışı bırakma, slab başına izleme ve bellek farkında havuz boyutlandırma özellikleriyle geliştirir.
KFENCE ne zaman kullanılır?
KFENCE, bellek karşılığında minimum CPU etkisi sunar ve iki kullanım senaryosunu destekler:
Üretim izleme: Filonuzda örneklem modunu etkinleştirin. Yeterli çalışma süresi olduğunda, KFENCE test iş yüklerinin nadiren çalıştırdığı kod yollarındaki hataları yakalar. En fazla 2 MiB bellek tüketir ve performans üzerinde ihmal edilebilir bir etki yaratır.
Çevrimdışı hata ayıklama: Belirli bir slab türü için tüm tahsisatları izlemek üzere tam modu etkinleştirin. GiB düzeyinde bellek tüketir ancak kapsam içindeki her tahsisatı yakalar. Bilinen sorunları yeniden üretmek için idealdir.
Çekirdek ve modül geliştiricileri, kodlarında bellek bozulmasını tespit etmek için KFENCE'i kullanabilir. Çökme yaşayan kullanıcılar, Alibaba Cloud veya üçüncü taraf sürücü geliştiricileri için çökme verilerini toplamak amacıyla KFENCE'i etkinleştirebilir.
Ön koşullar
KFENCE, aşağıdaki minimum çekirdek sürümlerine sahip Alibaba Cloud Linux 3 gerektirir:
|
|
|
|
|
|
|
|
|
KFENCE ve Çekirdek Adres Temizleyicisi (KASAN) Karşılaştırması
Her ikisi de yerleşik Linux çekirdek bellek bozulması algılayıcılarıdır. Alibaba Cloud, 5.10 çekirdeğinde KFENCE'i geliştirmiştir.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KFENCE ve KASAN'ı aynı anda etkinleştirmeyin. KFENCE, KASAN'ın izleme nesnelerinin kontrolünü devralır.
Temel kavramlar
|
|
|
|
|
|
|
|
|
|
|
|
KFENCE'i Etkinleştirme
Üretim izleme
Canlı bir ortamda minimum ek yükle bellek bozulmasını algılayın.
Senaryo 1: Önyükleme parametreleri aracılığıyla örneklem modu
KFENCE, bellek tahsisatlarını sabit bir aralıkla örnekler. Bellek tüketimi en fazla 2 MiB'dir ve ölçülebilir bir performans etkisi yoktur.
-
kfence.sample_intervalönyükleme parametresini ekleyin.<sample-interval>ifadesini milisaniye cinsinden örnekleme aralığıyla değiştirin. Örneğin,100= her 100 ms'de bir.sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.sample_interval=<sample-interval>" -
(İsteğe bağlı) Toplam sistem belleğine göre KFENCE belleğini sınırlamak için
kfence.booting_maxparametresini ekleyin.<booting-max>ifadesini0-128M:0,128M-256M:1M,256M-:2Mgibi bir segment gösterim dizisiyle değiştirin.sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.booting_max=<booting-max>" Yapılandırmanın etkili olması için işletim sistemini yeniden başlatın. Bir örneği yeniden başlatma.
Senaryo 2: Betik aracılığıyla belirli slab'ler için tam mod
Bu mod, belirtilen slab türleri için tüm tahsisatları izler. GiB düzeyinde bellek tüketir. Sınırlı belleğe sahip makinelerde dikkatli kullanın.
-
kfence.shadlı bir betik oluşturun. Betik, aktif slab nesnelerini sayar, havuzu boyutlandırır, diğer slab'ler ve order-0 sayfaları için izlemeyi devre dışı bırakır ve ardından belirtilen slab'ler için tam mod izlemeyi etkinleştirir.NotKFENCE hem slab'leri hem de order-0 sayfalarını izler. Slab'ler, sık kullanılan nesneler için çekirdeğin optimize edilmiş tahsis mekanizmasıdır.
#!/bin/bash # usage: ./kfence.sh kmalloc-64 SLAB_PREFIX=/sys/kernel/slab MODULE_PREFIX=/sys/module/kfence/parameters if [ $# -eq 0 ]; then echo "err: please input slabs" exit 1 fi #check whether slab exists for i in $@; do slab_path=$SLAB_PREFIX/$i if [ ! -d $slab_path ]; then echo "err: slab $i not exist!" exit 1 fi done #calculate num_objects sumobj=0 for i in $@; do objects=($(cat $SLAB_PREFIX/$i/objects)) maxobj=1 for ((j=1; j<${#objects[@]}; j++)); do nodeobj=$(echo ${objects[$j]} | awk -F= '{print $2}') [ $maxobj -lt $nodeobj ] && maxobj=$nodeobj done ((sumobj += maxobj)) done echo "recommend num_objects per node: $sumobj" #check kfence stats if [ $(cat $MODULE_PREFIX/sample_interval) -ne 0 ]; then echo "kfence is running, disable it and wait..." echo 0 > $MODULE_PREFIX/sample_interval sleep 1 fi #disable all slabs catching for file in $SLAB_PREFIX/* do (echo 0 > $file/kfence_enable) 2>/dev/null || echo 1 > $file/skip_kfence done #disable order0 page catching echo 0 > $MODULE_PREFIX/order0_page #enable setting slabs catching for i in $@; do (echo 1 > $SLAB_PREFIX/$i/kfence_enable) 2>/dev/null || echo 0 > $SLAB_PREFIX/$i/skip_kfence done #setting num_objects and node mode echo $sumobj > $MODULE_PREFIX/num_objects echo node > $MODULE_PREFIX/pool_mode #start kfence echo -1 > $MODULE_PREFIX/sample_interval if [ $? -ne 0 ]; then echo "err: kfence enable fail!" exit 1 fi echo "kfence enabled!" -
İzlenecek slab türüyle betiği çalıştırın:
sudo bash ./kfence.sh kmalloc-64
Çevrimdışı hata ayıklama
Geniş bir kapsam içindeki tüm bellek tahsisatlarını yakalayın. Yüksek bellek tüketimi, maksimum algılama kapsamı.
Önyükleme parametreleri (x86)
-
Aşağıdaki önyükleme parametrelerini ekleyin.
Parametre
Bu örnekteki değer
Etkinum_objects1000000
Havuz, en fazla 1.000.000 slab nesnesini izleyebilir ve ceil(1.000.000 / 131.071) = 8 GiB'a kadar bellek tüketir. Kullanılabilir belleğin yaklaşık %10'u olarak ayarlayın.sample_interval-1
Tam mod: Yapılandırılan kapsama uyan tüm belleği izler.faultpanic
Bir sorun algılandığında çekirdek paniği tetikler ve analiz için core dump'ı korur.sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.num_objects=1000000" sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.sample_interval=-1" sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.fault=panic" İşletim sistemini yeniden başlatın. Bir örneği yeniden başlatma.
Çalışma zamanı parametreleri (x86 veya Arm)
Çalışma zamanında etkinleştirilen KFENCE, çekirdek başlatma sırasındaki bellek bozulmasını algılayamaz.
KFENCE etkinleştirildikten sonra
num_objectsveyasample_intervaldeğerlerini değiştirmek için önce KFENCE'i devre dışı bırakın.num_objectsdeğişiklikleri, KFENCE bir sonraki kez etkinleştirildiğinde etkili olur.
Aşağıdaki komutları çalıştırın.
sudo sh -c 'echo 1000000 > /sys/module/kfence/parameters/num_objects'
sudo sh -c 'echo -1 > /sys/module/kfence/parameters/sample_interval'
sudo sh -c 'echo panic > /sys/module/kfence/parameters/fault'
Parametreler, yukarıdaki Önyükleme parametreleri (x86) bölümünde açıklanan değerlerle aynıdır.
Çekirdek sürümünüz 5.10.134-16 sürümünden önceyse, fault parametresi kullanılamaz. Bu parametreye yazarken alınan hata mesajı güvenle göz ardı edilebilir.
Sonuçları Kontrol Etme
KFENCE'i etkinleştirdikten sonra algılanan sorunları kontrol edin.
Algılama istatistiklerini görüntüleme
sudo cat /sys/kernel/debug/kfence/stats
Sorunlar algılandıysa, total bugs sayısı sıfırdan büyüktür.
Hata ayrıntılarını görüntüleme
dmesg | grep -i kfence
Çekirdek mesajlarını KFENCE hata raporları için filtreler.
KFENCE'i Devre Dışı Bırakma
KFENCE, Alibaba Cloud Linux çekirdek imajına yerleşik standart bir bileşendir (çekirdek yapılandırması CONFIG_KFENCE=y). Bir çekirdek yaması (kpatch), anlık güncelleme veya yazılım paketi aracılığıyla devre dışı bırakılamaz. Devre dışı bırakmak için aşağıdaki manuel komutu kullanın.
-
KFENCE izlemeyi durdurun. KFENCE, yeni tahsisatları izlemeyi bırakır. Havuzdaki izlenen tüm bellek serbest bırakıldığında, KFENCE bunu 1 GiB'lık artışlarla çekirdek buddy sistemine geri döndürür.
sudo bash -c 'echo 0 > /sys/module/kfence/parameters/sample_interval' -
(İsteğe bağlı) KFENCE önyükleme parametreleri aracılığıyla etkinleştirildiyse, bir sonraki önyüklemede KFENCE'in başlamasını önlemek için bunları kaldırın:
sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --remove-args="kfence.sample_interval"
Parametre Referansı
KFENCE'i önyükleme bağımsız değişkenleri aracılığıyla veya çalışma zamanında /sys/module/kfence/parameters/ yolu üzerinden yapılandırın.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Bellek tüketimi formülleri
Maksimum bellek tüketimi num_objects değerine bağlıdır:
num_objectsdeğeri 131.071'e eşit veya daha küçükse: (num_objects + 1) x 8 KiBnum_objectsdeğeri 131.071'den büyükse: ceil(num_objects / 131.071) GiB
Örneğin, num_objects değerini 1.000.000 olarak ayarlamak, ceil(1.000.000 / 131.071) = 8 GiB maksimum tüketime neden olur.
booting_max parametresi
kfence.booting_max parametresi, toplam sistem belleğine göre KFENCE belleğini sınırlar. Her segment, bir bellek aralığını bir KFENCE sınırına eşler.
Varsayılan yapılandırma (5.10.134-17 veya sonraki çekirdekler):
kfence.booting_max=0-2G:0,2G-32G:2M,32G-:32M
|
|
|
|
|
|
|
|
|
|
|
|
Varsayılan num_objects değeri 255 ile KFENCE bellek ek yükü, toplam belleğin binde birinin altında kalır. Standart 4 KiB sayfalarla maksimum tüketim 2 MiB'dir. 64 KiB devasa sayfalarla ise 32 MiB'dir.
booting_max parametresi yalnızca önyükleme sırasında num_objects değerini kısıtlar. Gerçek bellek tüketimi sınırdan daha az olabilir. Bu parametre, KFENCE çalışma zamanında etkinleştirildiğinde uygulanmaz.
Özel örnek: 0-128M:0,128M-256M:1M,256M-:2M
|
|
|
|
|
|
|
|
|
|
|
|