Korzystanie z ftrace

ftrace to narzędzie do debugowania, które pozwala zrozumieć, co dzieje się w jądrze Linuksa. Poniższe sekcje szczegółowo opisują podstawową funkcjonalność ftrace, użycie ftrace z atrace (który przechwytuje zdarzenia jądra) i dynamiczny ftrace.

Szczegółowe informacje na temat zaawansowanych funkcji ftrace, które nie są dostępne w systrace, można znaleźć w dokumentacji ftrace w <kernel tree>/Documentation/trace/ftrace.txt .

Przechwytywanie zdarzeń jądra za pomocą atrace

atrace ( frameworks/native/cmds/atrace ) używa ftrace do przechwytywania zdarzeń jądra. Z kolei systrace.py (lub run_systrace.py w późniejszych wersjach Catapult ) używa adb do uruchomienia atrace na urządzeniu. atrace wykonuje następujące czynności:

  • Konfiguruje śledzenie w trybie użytkownika, ustawiając właściwość ( debug.atrace.tags.enableflags ).
  • Włącza żądaną funkcjonalność ftrace poprzez zapisanie w odpowiednich węzłach ftrace sysfs. Jednakże, ponieważ ftrace obsługuje więcej funkcji, możesz samodzielnie ustawić niektóre węzły sysfs, a następnie użyć atrace.

Z wyjątkiem śledzenia czasu rozruchu, polegaj na użyciu atrace w celu ustawienia właściwości na odpowiednią wartość. Właściwość jest maską bitową i nie ma dobrego sposobu na określenie poprawnych wartości w inny sposób niż sprawdzenie odpowiedniego nagłówka (który może się zmieniać w zależności od wersji Androida).

Włączanie zdarzeń ftrace

Węzły ftrace sysfs znajdują się w /sys/kernel/tracing , a zdarzenia śledzenia są podzielone na kategorie w /sys/kernel/tracing/events .

Aby włączyć zdarzenia dla poszczególnych kategorii, użyj:

echo 1 > /sys/kernel/tracing/events/irq/enable

Aby włączyć zdarzenia dla poszczególnych zdarzeń, użyj:

echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable

Jeśli dodatkowe zdarzenia zostały włączone poprzez zapis do węzłów sysfs, nie zostaną one zresetowane przez atrace. Typowym wzorcem uruchamiania urządzenia Qualcomm jest włączenie punktów śledzenia kgsl (GPU) i mdss (potok wyświetlania), a następnie użycie atrace lub systrace :

adb shell "echo 1 > /sys/kernel/tracing/events/mdss/enable"
adb shell "echo 1 > /sys/kernel/tracing/events/kgsl/enable"
./systrace.py sched freq idle am wm gfx view binder_driver irq workq ss sync -t 10 -b 96000 -o full_trace.html

Możesz także użyć ftrace bez atrace lub systrace, co jest przydatne, gdy chcesz śledzić tylko jądro (lub jeśli poświęciłeś czas na ręczne napisanie właściwości śledzenia w trybie użytkownika). Aby uruchomić po prostu ftrace:

  1. Ustaw rozmiar bufora na wartość wystarczająco dużą dla Twojego śledzenia:
    echo 96000 > /sys/kernel/tracing/buffer_size_kb
    
  2. Włącz śledzenie:
    echo 1 > /sys/kernel/tracing/tracing_on
    
  3. Uruchom test, a następnie wyłącz śledzenie:
    echo 0 > /sys/kernel/tracing/tracing_on
    
  4. Zrzuć ślad:
    cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
    

Trace_output daje ślad w formie tekstowej. Aby to zwizualizować za pomocą Catapult, pobierz repozytorium Catapult z GitHub i uruchom trace2html:

catapult/tracing/bin/trace2html ~/path/to/trace_file

Domyślnie zapisuje plik trace_file.html w tym samym katalogu.

Powiązanie wydarzeń

Często przydatne jest jednoczesne spojrzenie na wizualizację Katapulty i dziennik śledzenia; na przykład niektóre zdarzenia ftrace (szczególnie te specyficzne dla dostawcy) nie są wizualizowane przez Catapult. Jednak znaczniki czasu Catapult są względne albo w stosunku do pierwszego zdarzenia w śladzie, albo do określonego znacznika czasu zrzuconego przez atrace, podczas gdy surowe znaczniki czasu ftrace są oparte na konkretnym źródle zegara bezwzględnego w jądrze Linuksa.

Aby znaleźć dane zdarzenie ftrace na podstawie zdarzenia katapulty:

  1. Otwórz surowy dziennik ftrace. Ślady w najnowszych wersjach systrace są domyślnie kompresowane:
    • Jeśli przechwyciłeś systrace za pomocą --no-compress , znajduje się to w pliku HTML w sekcji zaczynającej się od BEGIN TRACE.
    • Jeśli nie, uruchom html2trace z drzewa Catapult ( tracing/bin/html2trace ), aby zdekompresować ślad.
  2. Znajdź względny znacznik czasu w wizualizacji katapulty.
  3. Znajdź linię na początku śledzenia zawierającą tracing_mark_sync . Powinno to wyglądać mniej więcej tak:
    <5134>-5134  (-----) [003] ...1    68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
    

    Jeśli ta linia nie istnieje (lub jeśli użyłeś ftrace bez atrace), czasy będą względne w stosunku do pierwszego zdarzenia w dzienniku ftrace.
    1. Dodaj względny znacznik czasu (w milisekundach) do wartości w parent_ts (w sekundach).
    2. Wyszukaj nowy znacznik czasu.

Poniższe kroki powinny przybliżyć Cię do wydarzenia (lub przynajmniej bardzo blisko niego).

Korzystanie z dynamicznego ftrace

Gdy systrace i standardowy ftrace nie wystarczą, pozostaje jeszcze jedno rozwiązanie: dynamic ftrace . Dynamiczny ftrace polega na przepisaniu kodu jądra po uruchomieniu, w wyniku czego nie jest on dostępny w jądrach produkcyjnych ze względów bezpieczeństwa. Jednak każdy trudny błąd wydajności w latach 2015 i 2016 był ostatecznie spowodowany przez roota przy użyciu dynamicznego ftrace. Jest szczególnie przydatny do debugowania nieprzerwanego uśpienia, ponieważ możesz uzyskać ślad stosu w jądrze za każdym razem, gdy naciśniesz funkcję wyzwalającą nieprzerwany sen. Możesz także debugować sekcje z wyłączonymi przerwaniami i wywłaszczeniami, co może być bardzo przydatne przy udowadnianiu problemów.

Aby włączyć dynamiczny ftrace, edytuj defconfig jądra:

  1. Usuń CONFIG_STRICT_MEMORY_RWX (jeśli jest obecny). Jeśli masz wersję 3.18 lub nowszą i masz arm64, nie ma jej tam.
  2. Dodaj następujące elementy: CONFIG_DYNAMIC_FTRACE=y, CONFIG_FUNCTION_TRACER=y, CONFIG_IRQSOFF_TRACER=y, CONFIG_FUNCTION_PROFILER=y i CONFIG_PREEMPT_TRACER=y
  3. Odbuduj i uruchom nowe jądro.
  4. Uruchom następujące polecenie, aby sprawdzić dostępne znaczniki:
    cat /sys/kernel/tracing/available_tracers
    
  5. Potwierdź, że polecenie zwraca function , irqsoff , preemptoff i preemptirqsoff .
  6. Uruchom następujące polecenie, aby upewnić się, że dynamiczny ftrace działa:
    cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
    

Po wykonaniu tych kroków będziesz mieć do dyspozycji dynamiczny ftrace, profiler funkcji, profiler irqsoff i profiler wywłaszczania. Zdecydowanie zalecamy przeczytanie dokumentacji ftrace na te tematy przed ich użyciem, ponieważ są one potężne, ale złożone. irqsoff i preemptoff są przede wszystkim przydatne do sprawdzania, czy sterowniki mogą pozostawiać przerwania lub wywłaszczanie wyłączone na zbyt długo.

Profiler funkcji jest najlepszą opcją w przypadku problemów z wydajnością i często jest używany do sprawdzenia, gdzie funkcja jest wywoływana.


Jeśli dane z profilera funkcji nie są wystarczająco szczegółowe, możesz połączyć punkty śledzenia ftrace z profilerem funkcji. Zdarzenia ftrace można włączyć dokładnie w taki sam sposób jak zwykle i będą one przeplatane z Twoim śledzeniem. Jest to świetne rozwiązanie, jeśli od czasu do czasu występuje długi, nieprzerwany sen w określonej funkcji, którą chcesz debugować: ustaw filtr ftrace na żądaną funkcję, włącz punkty śledzenia, wykonaj śledzenie. Możesz przeanalizować wynikowy ślad za pomocą trace2html , znaleźć żądane zdarzenie, a następnie uzyskać pobliskie ślady stosu w nieprzetworzonym śladzie.

Korzystanie z lockstatu

Czasami ftrace nie wystarczy i naprawdę trzeba debugować coś, co wydaje się być rywalizacją o blokadę jądra. Warto wypróbować jeszcze jedną opcję jądra: CONFIG_LOCK_STAT . To ostateczność, ponieważ niezwykle trudno jest uruchomić system na urządzeniach z Androidem, ponieważ zwiększa to rozmiar jądra ponad możliwości większości urządzeń.

Jednak lockstat korzysta z infrastruktury blokowania debugowania, która jest przydatna w wielu innych aplikacjach. Każdy, kto pracuje nad konfiguracją urządzenia, powinien znaleźć sposób, aby ta opcja działała na każdym urządzeniu, ponieważ nadejdzie czas, gdy pomyślisz: „Gdybym tylko mógł włączyć LOCK_STAT , mógłbym potwierdzić lub odrzucić to jako problem w ciągu pięciu minut zamiast pięć dni."


Jeśli możesz uruchomić jądro za pomocą opcji konfiguracyjnej, śledzenie blokad jest podobne do ftrace:

  1. Włącz śledzenie:
    echo 1 > /proc/sys/kernel/lock_stat
    
  2. Uruchom test.
  3. Wyłącz śledzenie:
    echo 0 > /proc/sys/kernel/lock_stat
    
  4. Zrzuć swój ślad:
    cat /proc/lock_stat > /data/local/tmp/lock_stat
    

Aby uzyskać pomoc w interpretacji wynikowego wyniku, zapoznaj się z dokumentacją lockstat w <kernel>/Documentation/locking/lockstat.txt .

Korzystanie z punktów śledzenia dostawcy

Najpierw użyj wcześniejszych punktów śledzenia, ale czasami będziesz musiał użyć punktów śledzenia dostawcy:

  { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
        { OPT,      "events/mdss/enable" },
        { OPT,      "events/sde/enable" },
        { OPT,      "events/mali_systrace/enable" },
    } },

Punkty śledzenia można rozszerzyć za pomocą usługi HAL, co pozwala na dodawanie punktów/kategorii śledzenia specyficznych dla urządzenia. Punkty Tracepoints są zintegrowane z perfetto, atrace/systrace i aplikacją do śledzenia systemu na urządzeniu.

Interfejsy API służące do implementowania punktów/kategorii śledzenia to:

  • listCategories() generuje (kategorie vec<TracingCategory>);
  • EnableCategories(vec<string> kategorie) generuje (status stanu);
  • disableAllCategories() generuje (status stanu);
Aby uzyskać więcej informacji, zapoznaj się z definicją HAL i domyślną implementacją w AOSP :