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



Отладка обработчиков прерываний

Рассматриваются практики отладки обработчиков прерываний (ISR)

Статья включает:

Сложность отладки ISR
Отладка вне ядерного контекста
Системная трассировка
Вывод данных в отладочную консоль

Сложность отладки ISR

ISR исполняется в контексте ядра ОС и на его стеке. Таким образом, его отказоустойчивость влияет на всю систему в целом. При этом из обработчика нельзя вызывать любую функцию системной библиотеки, которая приводит к системному вызову.

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

В частности, все функции, которые порождают отправку сообщений не разрешены к применению в ISR. К ним относятся и функции семейства printf().

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

Отладка вне ядерного контекста

Одной из самых простых практик, но в ряде случаев являющихся разновидностью разрушающего контроля, является перевод обработки ISR на уровень прикладного потока. Для этого достаточно лишь оказаться от использования InterruptAttach() в пользу InterruptAttachEvent(). Хотя бы на время отладки.

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

Системная трассировка

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

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

Тем не менее, начиная с редакции 2024, ядро ЗОСРВ «Нейтрино» поддерживает postmortem трассировку ядра, которая позволяет получить фрагмент системной трассы, характеризующий последние мгновенья "жизни" ядра, включая отладку из ISR. Методика детально описана в статье Дампы ядра и их анализ.

Вывод данных в отладочную консоль

Начиная с редакции 2024, системная библиотека ЗОСРВ «Нейтрино» поддерживает группу функций, безопасных для получения печати из ISR в отладочную консоль в реальном времени:


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

Пример получения ISR-безопасной отладки:

#include <stdio.h>
#include <stdlib.h>
#include <sys/kprintf.h>
#include <sys/types.h>
#include <sys/neutrino.h>
struct sigevent *isr( void *arg, int id )
{
kprintf( "Hello, dudes!\n" );
return (NULL);
}
int main( int argc, char *argv[] )
{
...
kprintf_setup( kcallout_putchar, KPRINTF_DEFAULT_BEHAVIOR );
...
InterruptAttach( irq, isr, NULL, 0, _NTO_INTR_FLAGS_TRK_MSK );
...
}




Предыдущий раздел: Обработчики прерываний