4.
Диагностическая версия микроядра
Введение
Диагностическая
версия микроядра ОС QNX Neutrino (procnto-instr) оснащена сложным механизмом трассировки и
протоколирования, который позволяет оценить производительность
системы в реальном времени. Модуль procnto-instr работает как на однопроцессорных, так и
многопроцессорных системах.
Модуль procnto-instr
вносит весьма небольшие
накладные расходы и имеет исключительно высокую
производительность, которая, как правило, составляет около 98%
производительности обычного (noninstrumented) ядра с отключенным
протоколированием. Можно сказать, что дополнительный объем
программного кода диагностического ядра (около 30 Кбайт на
архитектуре x86) — сравнительно небольшая цена за
увеличение производительности и гибкости благодаря этому весьма
полезному инструменту. В зависимости от требований на
максимальный объем памяти для итоговой системы, эту специальную
версию ядра можно использовать либо как инструмент
разработки/создания прототипа, либо как рабочее ядро вашего
конечного продукта.
Диагностический модуль не требует изменения исходного кода
программы для мониторинга взаимодействия этой программы с ядром.
Трассировать можно сколько угодно взаимодействий между ядром и
любым активным потоком или процессом, — например, вызовы
ядра, изменения состояний и другие системные действия, в том
числе даже прерывания, — в этом смысле все эти
взаимодействия можно назвать событиями.
Более подробно см. в электронном документе «QNX Neutrino System Analysis Toolkit User’s Guide».
Общие сведения о
диагностическом механизме
На рисунке 4.1
приведены основные задачи, которые выполняет диагностическая
версия микроядра.
1. Диагностическое ядро (procnto-instr) генерирует трассировочные
события по различным системным операциям. Эти события
автоматически копируются в набор буферов, группированных в
циклическом связном списке (circular linked list).
2. Как только количество событий в буфере
достигает некоторого предела, ядро отправляет извещение
соответствующей утилите сбора данных.
3. Утилита сбора данных записывает
трассировочные события из буфера в устройство вывода
(например, последовательный порт, файл данных о событиях
и т. д.).
4. Затем специальный инструмент выполняет
интерпретацию полученных данных и отображает их для
пользователя.
Рис. 4.1. Схема диагностического механизма
Контроль событий
В реальной
системе производится огромное количество действий, поэтому
количество событий, генерируемых ядром, может быть чрезвычайно
большим (с точки зрения объема данных и ресурсов для их
обработки и хранения). Но все эти данные можно легко
контролировать с помощью:
-
управления условиями генерации
событий;
-
применения фильтров ядра для
динамического управления генерацией событий;
-
реализации собственных обработчиков
событий для расширенной фильтрации.
Данные, собранные
специальной утилитой (tracelogger), могут быть проанализированы
либо в реальном времени, либо автономно (по завершении
регистрации всех нужных событий). Инструмент системного анализа
(System Profilier), входящий в состав IDE, служит для графического
представления этих данных. Это позволяет пользователю "увидеть",
что именно происходит в системе.
Режимы генерации событий
Кроме применения
различных фильтров для отслеживания потока событий, можно задать
один из следующих двух режимов, которые ядро использует для
генерации событий:
-
быстрый (fast) — генерируется только
самая важная информация о событии (например, только два
аргумента вызова ядра);
-
расширенный (wide) — генерируется более
подробная информация о событии (например, все аргументы вызова ядра).
Выбор между этими
двумя режимами связан с предпочтением скорости или
детальности — быстрый режим генерирует меньше данных, а
расширенный режим генерирует значительно больше данных по
каждому событию. В любом случае генерацию событий в системе
можно легко изменять, так как оба режима допускают настройку по
каждому отдельному событию.
Для того чтобы проиллюстрировать разницу между быстрым и
расширенным режимом, рассмотрим, какого рода информацию можно
отследить, например, при вызове функции MsgSendv() — табл. 4.1 и 4.2.
Таблица 4.1. Быстрый режим
Тип данных
|
Число байтов на событие
|
Идентификационный номер соединения
|
4 байта
|
Данные сообщения
|
4 байта (первые 4 байта обычно
содержат заголовок)
|
|
Всего: 8 байтов
|
Таблица 4.2. Расширенный режим
Тип данных
|
Число байтов на событие
|
Идентификационный номер соединения
|
4 байта
|
Количество частей для передачи
|
4 байта
|
Количество частей для приема
|
4 байта
|
Данные сообщения
|
4 байта (первые 4 байта обычно
содержат заголовок)
|
Данные сообщения
|
4 байта
|
Данные сообщения
|
4 байта
|
|
Всего: 24 байта
|
Циклический буфер
Вместо того чтобы
всегда передавать трассировочные события на внешнее устройство,
ядро может хранить все эти события во внутреннем циклическом буфере.
При необходимости этот буфер может выводить свое содержимое на
внешнее устройство, когда возникают заданные условия, что делает
его мощным инструментом для выявления скрытых ошибок в процессе
исполнения.
Интерпретация данных
Данные,
характеризующие событие, включают в себя высокоточную временную
метку, а также идентификационный номер процессора, который
сгенерировал событие. По этой информации можно легко
диагностировать сложные проблемы согласования по времени,
которые чаще возникают в многопроцессорных системах.
Формат описания события также включает в себя информацию о типе
процессорной платформы (например, x86, PowerPC
и т. д.) и порядке следования байтов, что упрощает
выполнение дистанционного анализа (как в реальном времени, так и
автономно). С помощью интерпретатора данных выводимую информацию
можно отображать в разных представлениях, например:
-
линейное представление всей системы с
указанием временных меток;
-
текущее представление только активных
потоков/процессов;
-
представление событий по каждому
процессу/потоку с указанием текущих состояний.
Приведем пример
линейного представления информации, выводимой интерпретатором
данных:
TRACEPRINTER
version 0.94
-- HEADER FILE
INFORMATION --
TRACE FILE NAME::
/dev/shmem/tracebuffer
TRACE DATE:: Fri
Jun 8 13:14:40 2001
TRACE VER MAJOR:: 0
TRACE VER MINOR::
96
TRACE LITTLE
ENDIAN:: TRUE
TRACE ENCODING:: 16
byte events
TRACE BOOT DATE::
Fri Jun 8 04:31:05 2001
TRACE CYCLES PER
SEC:: 400181900
TRACE CPU NUM:: 4
TRACE SYSNAME:: QNX
TRACE NODENAME::
x86quad.gp.qa
TRACE SYS RELEASE::
6.1.0
TRACE SYS VERSION::
2001/06/04-14:07:56
TRACE MACHINE::
x86pc
TRACE SYSPAGE LEN::
2440
-- KERNEL EVENTS --
t:0x1310da15 CPU:01
CONTROL :TIME msb:0x0000000f, lsb(offset):0x1310d81c
t:0x1310e89d CPU:01
PROCESS :PROCCREATE NAME
ppid:0
pid:1
name:./procnto-smp-instr
t:0x1310eee4 CPU:00
THREAD :THCREATE pid:1 tid:1
t:0x1310f052 CPU:00
THREAD :THRUNNING pid:1 tid:1
t:0x1310f144 CPU:01
THREAD :THCREATE pid:1 tid:2
t:0x1310f201 CPU:01
THREAD :THREADY pid:1 tid:2
t:0x1310f32f CPU:02
THREAD :THCREATE pid:1 tid:3
t:0x1310f3ec CPU:02
THREAD :THREADY pid:1 tid:3
t:0x1310f52d CPU:03
THREAD :THCREATE pid:1 tid:4
t:0x1310f5ea CPU:03
THREAD :THRUNNING pid:1 tid:4
t:0x1310f731 CPU:02
THREAD :THCREATE pid:1 tid:5
.
.
.
Для настройки
интерпретации потока данных о событиях можно воспользоваться
специальной библиотекой (traceparser),
с помощью которой пользователь может написать свой собственный
интерпретатор событий.
Системный анализ с
помощью модуля IDE
IDE-модуль,
входящий в состав комплекта инструментов системного анализа
(System Analysis Toolkit, SAT), может служить в качестве
полнофункционального инструмента для измерительного контроля и
визуализации результатов обработки.
С помощью IDE-модуля SAT разработчики могут настраивать все
события и режимы трассировки, а также включать автоматическую
передачу файлов протоколирования на удаленную систему для
последующего анализа. В качестве инструмента визуализации,
IDE-модуль имеет большой набор фильтров событий и процессов,
которые предназначены помочь разработчикам быстро анализировать
большие массивы событий и делать из них нужную выборку.
Рис. 4.2. IDE-модуль позволяет визуализировать
функционирование системы
Дополнительные средства
трассировки
Диагностическая
версия микроядра предоставляет превосходные средства для
внешнего контроля и мониторинга процессов, потоков и состояний в
системе. Однако дополнительная возможность трассировки состоит в
том, что сами приложения можно настроить таким образом, чтобы
они влияли на процесс отслеживания событий.
С помощью библиотечной функции TraceEvent() приложения можно заставить вставлять заданные
события в общий поток событий. Этот механизм особенно полезен
при разработке больших, комплексных, многокомпонентных систем.
Например, следующий простой вызов будет передавать целочисленные
значения переменных eventcode, first и second в общий поток событий.
TraceEvent(
NTO TRACE INSERTSUSEREVENT, eventcode, first, second);
Кроме того, можно передавать и символьные строки (например, "Мое
событие"). Например:
#include <stdio.h>
#include <sys/trace.h>
/* Код, который будет
ассоциироваться с передаваемыми событиями. */
#define MYEVENTCODE
12
int main(int argc,
char **argv) {
printf("My pid is
%d \n", getpid());
/* Вставить два
события целочисленного типа (26, 1975) */
TraceEvent( NTO
TRACE INSERTSUSEREVENT, MYEVENTCODE, 26, 1975);
/* Вставить событие символьного
типа (Мое событие). */
TraceEvent(
NTO TRACE INSERTUSRSTREVENT, MYEVENTCODE, "My Event");
return 0;
}
В результате выполнения этого кода данные, собранные
интерпретатором traceprinter, могут выглядеть, например,
следующим образом:
.
.
.
t:0x38ea737e CPU:00
USREVENT:EVENT:12, d0:26 d1:1975
.
.
.
t:0x38ea7cb0 CPU:00
USREVENT:EVENT:12 STR:"My Event"
Число 12 означает код трассировочного события, соответствующий
указанным событиям.