ftrace – это инструмент отладки, который позволяет понять, что происходит внутри ядра Linux. В следующих разделах подробно описаны основные функции ftrace, использование ftrace с atrace (для сбора событий ядра) и динамический ftrace.
Подробную информацию о расширенных функциях ftrace, недоступных в systrace, можно найти в документации по ftrace на сайте <kernel
tree>/Documentation/trace/ftrace.txt.
Как записывать события ядра с помощью atrace
Утилита atrace (frameworks/native/cmds/atrace) использует ftrace для сбора событий ядра. В свою очередь, systrace.py (или run_systrace.py в более поздних версиях Catapult) использует adb для запуска atrace на устройстве. atrace выполняет следующие действия:
- Настраивает трассировку в режиме пользователя, задавая свойство (
debug.atrace.tags.enableflags). - Включает нужные функции ftrace, записывая данные в соответствующие узлы sysfs. Однако, поскольку ftrace поддерживает больше функций, вы можете самостоятельно задать некоторые узлы sysfs, а затем использовать atrace.
За исключением трассировки во время загрузки, для установки подходящего значения свойства следует использовать atrace. Это битовая маска, и определить правильные значения можно только посмотрев соответствующий заголовок (который может меняться в разных версиях Android).
Включить события ftrace
Узлы sysfs ftrace находятся в /sys/kernel/tracing, а события трассировки разделены на категории в /sys/kernel/tracing/events.
Чтобы включить события по категориям, используйте:
echo 1 > /sys/kernel/tracing/events/irq/enable
Чтобы включить события на уровне отдельных событий, используйте:
echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable
Если дополнительные события были включены путем записи в узлы sysfs, они не будут сброшены с помощью atrace. При настройке устройств Qualcomm часто включают точки трассировки kgsl (графический процессор) и mdss (конвейер дисплея), а затем используют atrace или 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
Вы также можете использовать ftrace без atrace или systrace, что полезно, когда вам нужны трассировки только ядра (или если вы потратили время на то, чтобы вручную написать свойство трассировки в пользовательском режиме). Чтобы запустить только ftrace:
- Установите размер буфера, достаточный для трассировки:
echo 96000 > /sys/kernel/tracing/buffer_size_kb
- Включить трассировку:
echo 1 > /sys/kernel/tracing/tracing_on
- Запустите тест, а затем отключите трассировку:
echo 0 > /sys/kernel/tracing/tracing_on
- Чтобы сохранить трассировку:
cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
trace_output – трассировка в текстовом формате. Чтобы визуализировать его с помощью Catapult, получите хранилище Catapult с GitHub и запустите trace2html:
catapult/tracing/bin/trace2html ~/path/to/trace_file
По умолчанию в том же каталоге создается файл trace_file.html.
Сопоставление событий
Часто бывает полезно одновременно просматривать визуализацию Catapult и журнал ftrace. Например, некоторые события ftrace (особенно специфичные для поставщика) не визуализируются Catapult. Однако временные метки Catapult относительны: они отсчитываются от первого события в трассировке или от определенной временной метки, полученной с помощью atrace. Временные метки ftrace основаны на определенном абсолютном источнике времени в ядре Linux.
Чтобы найти событие ftrace по событию Catapult, выполните следующие действия:
- Откройте необработанный журнал ftrace. В последних версиях systrace трассировки по умолчанию сжимаются:
- Если вы записали systrace с помощью
--no-compress, то эта информация будет в HTML-файле в разделе, начинающемся с BEGIN TRACE. - Если нет, запустите html2trace из дерева Catapult (
tracing/bin/html2trace), чтобы распаковать трассировку.
- Если вы записали systrace с помощью
- Найдите относительную временную метку в визуализации Catapult.
- Найдите в начале трассировки строку, содержащую
tracing_mark_sync. Пример:<5134>-5134 (-----) [003] ...1 68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
Если этой строки нет (или вы использовали ftrace без atrace), то время будет отсчитываться от первого события в журнале ftrace.- Добавьте относительную временную метку (в миллисекундах) к значению в
parent_ts(в секундах). - Найдите новую временную метку.
- Добавьте относительную временную метку (в миллисекундах) к значению в
Вы должны оказаться на месте проведения мероприятия или очень близко к нему.
Как использовать динамическую трассировку функций
Если возможностей systrace и стандартного ftrace недостаточно, можно воспользоваться динамическим ftrace. Динамическая трассировка ftrace предполагает перезапись кода ядра после загрузки, поэтому она недоступна в рабочих ядрах из соображений безопасности. Однако все сложные ошибки производительности в версиях 2015 и 2016 годов были в конечном итоге выявлены с помощью динамической трассировки ftrace. Это особенно полезно для отладки непрерывных спящих режимов, поскольку вы можете получать трассировку стека в ядре каждый раз, когда вы нажимаете функцию, запускающую непрерывный спящий режим. Вы также можете отлаживать разделы с отключенными прерываниями и вытеснениями, что может быть очень полезно для подтверждения проблем.
Чтобы включить динамическую трассировку ftrace, измените файл defconfig ядра:
- Удалите CONFIG_STRICT_MEMORY_RWX (если он есть). Если у вас версия 3.18 или более новая и архитектура arm64, его там нет.
- Добавьте следующие строки: CONFIG_DYNAMIC_FTRACE=y, CONFIG_FUNCTION_TRACER=y, CONFIG_IRQSOFF_TRACER=y, CONFIG_FUNCTION_PROFILER=y и CONFIG_PREEMPT_TRACER=y.
- Пересоберите и загрузите новое ядро.
- Чтобы проверить доступные трассировщики, выполните следующую команду:
cat /sys/kernel/tracing/available_tracers
- Убедитесь, что команда возвращает значения
function,irqsoff,preemptoffиpreemptirqsoff. - Чтобы убедиться, что динамическая трассировка ftrace работает, выполните следующую команду:
cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
После выполнения этих шагов вам будут доступны динамическая трассировка ftrace, профилировщик функций, профилировщик irqsoff и профилировщик preemptoff. Мы настоятельно рекомендуем ознакомиться с документацией по ftrace, прежде чем использовать эти инструменты, поскольку они мощные, но сложные. irqsoff и preemptoff в основном полезны для подтверждения того, что драйверы могут оставлять прерывания или вытеснение отключенными слишком долго.
Профайлер функций лучше всего подходит для решения проблем с производительностью и часто используется для определения того, где вызывается функция.
Если данные из профилировщика функций недостаточно конкретны, вы можете объединить точки трассировки ftrace с профилировщиком функций. События ftrace можно включить точно так же, как обычно, и они будут чередоваться с вашей трассировкой.
Это удобно, если в определенной функции, которую вы хотите отладить, иногда происходит длительный непрерывный переход в спящий режим: задайте фильтр ftrace для нужной функции, включите точки трассировки и выполните трассировку. Вы можете проанализировать полученную трассировку с помощью trace2html, найти нужное событие, а затем получить ближайшие трассировки стека в необработанной трассировке.
Как использовать lockstat
Иногда ftrace недостаточно, и вам действительно нужно отладить то, что выглядит как конфликт блокировок ядра. Есть ещё один параметр ядра, который стоит попробовать:
CONFIG_LOCK_STAT. Это крайняя мера, поскольку ее очень сложно реализовать на устройствах Android, так как она увеличивает размер ядра до значений, которые большинство устройств не могут обработать.
Однако lockstat использует инфраструктуру блокировки отладки, которая полезна для многих других приложений. Каждый, кто работает над запуском устройства, должен найти способ включить эту функцию на каждом устройстве, потому что наступит момент, когда вы подумаете: "Если бы я мог включить LOCK_STAT, я бы подтвердил или опроверг эту проблему за пять минут, а не за пять дней".
Если вы можете загрузить ядро с параметром config, то отслеживание блокировок будет похоже на ftrace:
- Включить трассировку:
echo 1 > /proc/sys/kernel/lock_stat
- Запустите тест.
- Отключить трассировку:
echo 0 > /proc/sys/kernel/lock_stat
- Выгрузите трассировку:
cat /proc/lock_stat > /data/local/tmp/lock_stat
Чтобы узнать, как интерпретировать полученные результаты, ознакомьтесь с документацией по lockstat на странице <kernel>/Documentation/locking/lockstat.txt.
Как использовать точки трассировки поставщиков
Сначала используйте точки трассировки upstream, но иногда вам придется использовать точки трассировки поставщика:
{ "gfx", "Graphics", ATRACE_TAG_GRAPHICS, {
{ OPT, "events/mdss/enable" },
{ OPT, "events/sde/enable" },
{ OPT, "events/mali_systrace/enable" },
} },
Точки трассировки можно расширять с помощью сервиса HAL, добавляя точки трассировки и категории, относящиеся к определенному устройству. Точки трассировки интегрированы с perfetto, atrace/systrace и приложением для трассировки системы на устройстве.
Для реализации точек трассировки и категорий используются следующие API:
- listCategories()generates (vec<TracingCategory> categories);
- enableCategories(vec<string> categories) generates (Status status);
- disableAllCategories() generates (Status status);