Трассировка пользовательских приложений
Основные идеи, понятия и объекты
Под трассировкой в стандарте POSIX-2001 понимается порождение, накопление и анализ данных о событиях, имевших место при выполнении пользовательского приложения.
Применительно к приложениям реального времени трассировка помогает достичь по крайней мере трех целей:
- оптимизировать структуру приложения на основе анализа трассировочных данных (например, попытаться сгладить пики активности, распределить нагрузку равномерно по времени);
- отладить приложение (традиционные интерактивные отладчики могут быть неприменимы к приложениям реального времени);
- выявить причину аварийного завершения работы приложения (обнаружить место и первые признаки ненормального поведения).
С логической точки зрения в трассировке (в том виде, как она рассматривается в стандарте POSIX-2001) участвуют три процесса (физически они могут совпадать между собой):
- трассируемый ( целевой );
- трассирующий ( управляющий трассировкой );
- анализирующий данные трассировки.
Сведения о действиях, производимых при выполнении приложения, фиксируются в виде объектов данных, называемых событиями трассировки (или, для краткости, просто событиями ). События записываются в потоки трассировки, которые содержат также служебные данные, необходимые для интерпретации событий .
Трассируемый процесс должен быть специальным образом оборудован: его программа должна содержать точки трассировки – действия, способные генерировать события трассировки. Для каждого трассируемого процесса должен быть открыт по крайней мере один поток трассировки.
Процесс, создавший поток трассировки, называется трассирующим ( управляющим трассировкой ).
Анализирующим называется процесс, извлекающий события трассировки из потока с целью получения информации о поведении трассируемого приложения.
Одним из главных требований к системе трассировки является минимизация накладных расходов. Чтобы выполнить это требование, потоки трассировки, как правило, хранят только в оперативной памяти. Если нужно получить стабильную копию потока для последующего анализа, его следует сбросить в журнал трассировки, располагающийся в долговременной памяти.
События трассировки подразделяются на две категории:
- пользовательские ;
- системные.
Пользовательские события генерируются при вызове функции posix_trace_event().
Системные события генерируются реализацией в ответ на действия ОС или приложения. Отметим, что в первом случае событие не ассоциировано с каким-либо процессом.
У событий трассировки есть типы и имена, между которыми устанавливается взаимно-однозначное соответствие (вообще говоря, свое для каждого потока). Удобочитаемые имена предназначены для человека; в потоке трассировки хранятся идентификаторы типов событий (и таблица соответствия имен и идентификаторов типов).
В стандарте POSIX-2001 специфицированы следующие типы системных событий, анализ которых помогает интерпретировать поток трассировки.
POSIX_TRACE_START
Начало трассировки.
POSIX_TRACE_STOP
Приостановка трассировки.
POSIX_TRACE_OVERFLOW
Возникновение ситуации переполнения потока трассировки.
POSIX_TRACE_RESUME
Устранение ситуации переполнения потока трассировки.
POSIX_TRACE_FLUSH_START
Начало сброса потока трассировки в журнал.
POSIX_TRACE_FLUSH_STOP
Завершение сброса потока трассировки в журнал.
POSIX_TRACE_ERROR
Ошибка трассировки, зависящая от реализации.
Стандартизован также один тип пользовательских событий – POSIX_TRACE_UNNAMED_USEREVENT. Это значение возвращается, когда приложение пытается зарегистрировать больше имен событий, чем допускается в соответствии со значением конфигурационной константы TRACE_USER_EVENT_MAX.
Стандартом POSIX-2001 предусмотрен механизм фильтрации, позволяющий отключить генерацию событий определенных типов и, тем самым, уменьшать объем трассировочных данных. Это полезно, например, в ситуациях, когда у приложения есть заведомо "неинтересные" фрагменты, трассировать которые нет смысла, или многочисленные системные события (такие, например, как переключение контекстов), "неинтересные" с точки зрения приложения.
Фильтр устанавливает трассирующий процесс. По умолчанию события не фильтруются.
При смене фильтра генерируется системное событие POSIX_TRACE_FILTER.
Ключевыми элементами реализации средств трассировки являются описанные в заголовочном файле <trace.h> структуры posix_trace_event_info и posix_trace_status_info. Первая специфицирует формат событий, вторая – данные, хранящиеся в потоке трассировки.
Согласно стандарту POSIX-2001, структура типа posix_trace_event_info должна содержать по крайней мере следующие поля.
trace_event_id_t posix_event_id; /* Идентификатор типа события */ pid_t posix_pid; /* Идентификатор трассируемого процесса */ void *posix_prog_address; /* Адрес точки трассировки */ int posix_truncation_status; /* Признак усечения данных */ struct timespec posix_timestamp; /* Временной штамп события */ pthread_t posix_thread_id; /* Идентификатор трассируемого потока управления */
Смысл некоторых полей, вероятно, нуждается в пояснении.
Если, в соответствии с типом (поле posix_event_id ) событие является системным и не ассоциировано с каким-либо процессом, значение posix_pid должно быть нулевым.
Для пользовательских событий в поле posix_prog_address помещается адрес вызова posix_trace_event(); для системных, сгенерированных в результате явного обращения приложения к системному сервису (такому, например, как fork() ), в этом поле находится адрес вызова системного сервиса.
В поле posix_truncation_status хранится признак того, были ли данные усечены при генерации или чтении события. Возможных значения три:
POSIX_TRACE_NOT_TRUNCATED
Доступны все данные, ничего не усечено.
POSIX_TRACE_TRUNCATED_RECORD
Данные усечены при генерации.
POSIX_TRACE_TRUNCATED_READ
Данные усечены при чтении (буфер оказался мал). Это значение подавляет признак усечения при генерации.
В поле posix_timestamp помещается время генерации события. Выбор используемых для этого часов осуществляется реализацией.
Поле posix_thread_id по смыслу и трактовке близко к posix_pid, только в нем хранится идентификатор потока, а не процесса (если, конечно, реализация поддерживает потоки).