Операционная система ЗОСРВ «Нейтрино» > Руководство разработчика > Основные принципы системной разработки > Программные интерфейсы микроядра > Системная трассировка и анализ > Сбор трассировочных данных



Сбор трассировочных данных

Сохранение данных системной трассы

В этой главе:

Обзор
Управление трассировкой с помощью утилиты tracelogger
Управление трассировочными буферами
Режимы работы утилиты tracelogger
Выбор между кратким и подробным режимами
Фильтрация событий
Передача трассировочных данных
Управление трассировкой с помощью функции TraceEvent()
Управление трассировочными буферами
Режимы работы
Фильтрация событий
Выбор между кратким и подробным режимами
Вставка трассировочных событий
Трасировка в момент падения ядра

Обзор

Программа сбора данных является посредником между диагностической версией ядра и файловой системой.

data_capture.png
Рисунок 1. Возможные конфигурации сбора данных

Основная задача программы сбора данных — передача буферов, полученных от диагностической версии ядра, в файл или на устройство вывода. Для выполнения этой функции программе также необходимо:

Перед регистрацией данных необходимо настраивать диагностическую версию ядра. Конфигурация диагностической версии ядра включает в себя следующие настройки:


Note: Диагностическая версия ядра сохраняет настройки в одной конфигурации, которой пользуются различные программы. Изменение настроек в одном процессе приводит к отмене настроек, заданных в другом процессе.

По умолчанию для сбора данных используется утилита tracelogger. При желании пользователь может создать собственную утилиту, однако в этом, как правило, нет необходимости; тем не менее, при возникновении такой задачи самым быстрым способом ее решения является адаптация кода утилиты tracelogger под потребности пользователя.

Управлять сбором данных можно с помощью демона qconn (используя внешние средства), утилиты tracelogger (из командной строки) или непосредственно из пользовательского приложения. Во всех трех методах управление диагностическим ядром осуществляется с помощью функции TraceEvent():

trace_control.png
Рисунок 2. Управление сбором трассировочных данных

Сначала рассмотрим утилиту tracelogger, а затем управление трассировкой из пользовательского приложения с помощью функции TraceEvent().


Caution:
  • Не следует запускать более одного экземпляра утилиты tracelogger, а также использовать ее одновременно с трассировкой событий через qconn.

  • Если в многоядерной системе часы процессоров не синхронизированы, утилита tracelogger генерирует некорректные отметки времени. Утилита traceprinter беспрепятственно обрабатывает такие трассировки, поскольку не пытается переупорядочивать и интерпретировать данные; она всего лишь регистрирует содержимое каждого события.

Управление трассировкой с помощью утилиты tracelogger

Параметры запуска утилиты tracelogger определяют, каким образом диагностическая версия ядра регистрирует события и как tracelogger собирает их. В этом разделе рассматриваются следующие темы:

Управление трассировочными буферами

Для управления буферами диагностической версии ядра можно использовать командно-строковые параметры утилиты tracelogger:

Также можно задавать количество буферов, используемых самой утилитой tracelogger.

Режимы работы утилиты tracelogger

С помощью командно-строковых аргументов можно запускать утилиту tracelogger в различных режимах, которые определяют, как выполняется трассировка и какие события участвуют в ней:

-n итерации
Ядро регистрирует события, утилита tracelogger собирает данные в буферах, количество которых равно значению параметра итерации и завершается. Этот режим используется по умолчанию, а количество итераций равно 32.
-r
Кольцевой режим: ядро сохраняет все события в циклическом связанном списке буферов, не очищая их. Максимальная длительность сбора событий без перезаписи зависит от количества выделенных буферов и генерируемых трассировочных событий.

В кольцевом режиме утилита tracelogger не регистрирует события до тех пор, пока не получает сигнал SIGINT (например, когда пользователь нажимает клавиши Ctrl - C) или приложение не вызывает команду TraceEvent() функции _NTO_TRACE_STOP.

Если параметр -r не указан, утилита tracelogger работает в линейном режиме; сбор и очистка каждого полного буфера осуществляются немедленно.
-d1
Режим демона: ядро не регистрирует события, а утилита tracelogger не собирает их до тех пор, пока приложение не вызывает команду _NTO_TRACE_START функции TraceEvent(). События регистрируются до тех пор, пока приложение не вызывает команду _NTO_TRACE_STOP функции TraceEvent() или утилита tracelogger не завершает работу.

Note: В режиме демона утилита tracelogger игнорирует все остальные параметры, если не указан дополнительный параметр -E , который включает расширенный режим демона.

-s секунды
Ядро регистрирует события, а утилита tracelogger собирает их на протяжении указанного периода времени.
-c
Ядро регистрирует события, а утилита tracelogger собирает их до тех пор, пока пользователь не завершает ее работу.

Все описанные выше режимы, за исключением режима демона, в совокупности называются нормальным режимом. В нормальном режиме настройка, запуск и останов трассировки выполняются в командной строке, а в режиме демона (-d1) — в коде приложения. Параметр -E позволяет использовать возможности обоих режимов: командно-строковую настройку трассировки (как в нормальном режиме) и полный контроль над ней (как в режиме демона).

Ниже перечислены преимущества, недостатки и возможности указанных режимов:

Функция Нормальный режим Режим демона Расширенный режим демона
Поддержка tracelogger Полная Ограниченная Полная
Управляемость Ограниченная Полная Полная
События, регистрируемые по умолчанию Все Никакие Все
Степень сложности настройки Легкая Более сложная Легкая
Метод настройки Только командная строка Пользовательская программа, в которой вызывается функция TraceEvent() Командная строка и пользовательская программа
Начало регистрации событий Моментально В пользовательской программе (также с вызовом TraceEvent()) В пользовательской программе (также с вызовом TraceEvent())

Полное описание утилиты tracelogger дано на соответствующей странице.

Выбор между кратким и подробным режимами

По умолчанию диагностическая версия ядра и утилита tracelogger собирают данные в кратком режиме; чтобы включить подробный режим, следует указать ключ -w при запуске tracelogger.

Фильтрация событий

Утилита tracelogger обеспечивает основные функции управления фильтрацией с помощью ключа -F. Он позволяет отключать регистрацию целых классов событий; для более точной настройки следует использовать функцию TraceEvent(), которая описана в главе Фильтрация событий.

По умолчанию утилита tracelogger регистрирует события всех классов, однако можно отключать трассировку событий определенного класса следующим образом:

Отключаемый класс Опция
Вызовы ядра -F1
Прерывания -F2
Процессы -F3
Потоки -F4
Виртуальные потоки -F5
Связь -F6
Система -F7

Можно задавать более одного фильтра, указывая ключ -F несколько раз. Следует иметь в виду, что этот ключ не позволяет отключать классы управления и пользователя. Более подробную информацию о классах см. в главе События ядра в системной трассе.

Передача трассировочных данных

Поскольку кольцевого связанного списка может оказаться недостаточно для хранения всех событий за длительный промежуток времени, необходимо передавать трассировочный буфер программе сбора данных. Как правило, эта программа отправляет данные на устройство вывода или в файл.

По умолчанию утилита tracelogger сохраняет данные в двоичном файле /dev/shmem/tracebuffer.kev, однако можно задать другой путь с помощью параметра -f.

Также можно размещать файл в общей памяти с помощью ключа -M, однако в этом случае необходимо указывать его максимальный размер с помощью ключа -S.

Управление трассировкой с помощью функции TraceEvent()

Управлять трассировкой можно не только с помощью утилиты tracelogger, но и непосредственно с помощью функции TraceEvent(), которая фактически используется утилитой tracelogger. Управление трассировкой с помощью TraceEvent() более трудоемкое, однако позволяет задавать гораздо больше различных параметров.

Можно вообще не использовать утилиту tracelogger и работать исключительно с функцией TraceEvent(), но в этом случае необходимо управлять буферами, собирать трассировочные данные и сохранять их в подходящем формате. Такой подход требует от разработчика написания значительного количества программного кода, однако исходный код утилиты tracelogger облегчает эту задачу.

На практике целесообразно совместно использовать утилиту tracelogger и функцию TraceEvent(). Например, можно управлять трассировочными данными, выполняя утилиту tracelogger в режиме демона, и вызывать функцию TraceEvent() для указания конкретных событий, участвующих в трассировке.

Вызов ядра TraceEvent() принимает различное количество аргументов. Первым аргументом всегда является команда, от которой зависит набор последующих аргументов.

В этом разделе рассматриваются следующие темы:

Подробнее см. на странице TraceEvent().

Управление трассировочными буферами

Как было сказано ранее, функция TraceEvent() позволяет управлять буферами диагностического ядра, однако удобнее следить за буферами, выполняя утилиту tracelogger в режиме демона. Тем не менее, ниже перечислены команды управления буферами функции TraceEvent():

Режимы работы

Функция TraceEvent() не поддерживает различные режимы работы, предусмотренные в утилите tracelogger; разработчик должен указывать в приложении момент начала трассировки, ее длительность и другие параметры:

Фильтрация событий

Можно добавлять и удалять события из фильтра — например, создавать пустой фильтр и включать в него конкретные классы и события, или включать в фильтр все события, а затем удалять некоторые из них. Мы рассмотрим фильтрацию событий с помощью функции TraceEvent() в главе Фильтрация событий.

Выбор между кратким и подробным режимами

Функция TraceEvent() обеспечивает значительно более гибкое управление кратким и подробным режимами, чем утилита tracelogger, которая только задает режим для всех событий всех классов, участвующих в трассировке. С помощью функции TraceEvent() you can set можно назначать краткий и подробный режимы всем или некоторым классам, а также конкретным событиям определенного класса:

Вставка трассировочных событий

Функция TraceEvent() позволяет вставлять пользовательские события в трассировочные данные. Можно вызывать ее непосредственно, однако гораздо удобнее использовать следующие вспомогательные функции:

trace_func_enter()
Вставляет в трассировку событие входа в функцию.
trace_func_exit()
Вставляет в трассировку событие выхода из функции.
trace_here()
Вставляет в трассировку событие текущего адреса.
trace_logb()
Вставка составного трассировочного пользовательского события.
trace_logbc()
Вставляет в трассировку событие произвольного класса и типа с любыми данными.
trace_logf()
Вставка строкового пользовательского трассировочного события.
trace_logi()
Вставка простого пользовательского трассировочного события.
trace_nlogf()
Вставка строкового пользовательского трассировочного события с указанием максимальной длины строки.
trace_vnlogf()
Вставка строкового пользовательского трассировочного события со списком из переменного количества аргументов.

Чтобы непосредственно вызвать функцию TraceEvent(), следует воспользоваться одной из следующих команд:

Дополнительную информацию см. в описании функции TraceEvent().

Трасировка в момент падения ядра

При отладке ситуаций, связанных с падением ядра, бывает очень полезно узнать последние выполнявшиеся действия. Выполнить это можно путем расширения информации, включаемой в дамп ядра. Процедура детально описана в статье Postmortem трассировка ядра.




Предыдущий раздел: перейти