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



События ядра в системной трассе

Концепция событий ядра при трассировке

В этой главе:

Источники событий
Генерация событий: типичный сценарий
Пример многопоточной программы
Время переключения контекста потока
Перезапуск потоков
Простые и составные события
Краткий (fast) и подробный (wide) режимы
Классы и события
Класс событий связи: _NTO_TRACE_COMM
Класс событий управления: _NTO_TRACE_CONTROL
Класс событий обработки прерываний: _NTO_TRACE_INTENTER, _NTO_TRACE_INTEXIT, _NTO_TRACE_INT_HANDLER_ENTER и _NTO_TRACE_INT_HANDLER_EXIT
Класс событий вызовов ядра: _NTO_TRACE_KERCALLENTER, _NTO_TRACE_KERCALLEXIT и _NTO_TRACE_KERCALLINT
Класс событий процессов: _NTO_TRACE_PROCESS
Класс системных событий: _NTO_TRACE_SYSTEM
Класс событий потоков: _NTO_TRACE_THREAD
Пользовательский класс: _NTO_TRACE_USER
Класс событий виртуальных потоков: _NTO_TRACE_VTHREAD

Источники событий

Микроядро ЗОСРВ «Нейтрино» генерирует события не только для системных вызовов, но и для других действий, в числе которых:

Диагностическая версия ядра также вставляет «искусственные» события:

Некоторые вызовы ядра и действия в системе могут приводить к генерации нескольких событий.

Генерация событий: типичный сценарий

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

Пример многопоточной программы

В этом примере используются два потока:

Мы будем наблюдать за их выполнением, считая, что они запускаются одновременно:


Note: Когда начинается ведение журнала, диагностическая версия ядра регистрирует в нем информацию о каждом потоке. Во время этой процедуры создаются существующие процессы.

Время Поток Действие Комментарий
t1 A Создание Выполняется создание потока.
t2 A Блокировка Для продолжения работы потоку необходимо дождаться, например, окончания операции ввода/вывода.
t3 B Создание Ядро не простаивает, а запускает следующий поток с наивысшим приоритетом.
t4 B Системный вызов Поток B выполняется.
t4.5 Н/Д Н/Д Ввод/вывод завершен; поток A готов к выполнению.
t5 B Блокировка Поток A готов к выполнению и вытесняет поток B.
t6 A Выполнение Поток A продолжает выполнение.
t7 A Завершение Поток заканчивает работу и завершается.
t8 B Выполнение Поток B продолжает выполнение с места блокировки.
t9 ... ... ...

Время переключения контекста потока

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

timing.png
Рисунок 1. Переключение контекста потоков

Иногда два или более потоков чередуются друг с другом, не выполняя полезной работы. Это похоже на двух чрезмерно вежливых людей, которые пытаются войти в одну дверь — каждый предлагает другому пройти первым, и в результате ни один из них не попадает внутрь вовремя (в аналогичной ситуации оказываются и два агрессивных человека). Инструменты системного анализа позволяют легко и быстро обнаруживать такие неполадки. Сопоставляя операции переключения контекста с изменениями состояния потоков, разработчик с легкостью определяет причины «зависания» систем, которые в остальное время работают быстро.

Перезапуск потоков

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

Простые и составные события

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

Дополнительную информацию о простых и составных событиях см. в главе Интерпретация трассировочных данных.

Краткий (fast) и подробный (wide) режимы

Можно собирать данные событий в следующих режимах:

Подробный режим (wide mode)
Диагностическая версия ядра регистрирует всю информацию события, используя для этого любое необходимое количество элементов буфера. Объем данных события теоретически не ограничен и может составлять до нескольких килобайт. Как правило, одно событие занимает не более четырех 16-байтовых элемента.
Краткий режим (fast mode)
Диагностическая версия ядра помещает событие в единственный элемент буфера.

Как правило, в подробном режиме данные событий занимают в несколько раз больше места, чем в кратком.


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

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

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

Классы и события

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

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

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

Класс событий связи: _NTO_TRACE_COMM

Класс _NTO_TRACE_COMM включает в себя события, которые относятся к сообщениям и импульсам:

Событие Метка traceprinter Условие генерации события
_NTO_TRACE_COMM_ERROR MSG_ERROR Разблокирование клиента вызовом MsgError()
_NTO_TRACE_COMM_REPLY REPLY_MESSAGE Отправка ответа
_NTO_TRACE_COMM_RMSG REC_MESSAGE Прием сообщения
_NTO_TRACE_COMM_RPULSE REC_PULSE Прием импульса
_NTO_TRACE_COMM_SIGNAL SIGNAL Прием сигнала
_NTO_TRACE_COMM_SMSG SND_MESSAGE Отправка сообщения
_NTO_TRACE_COMM_WRITE WRITE Отправка сообщений с помощью write*()
_NTO_TRACE_COMM_SPULSE SND_PULSE Отправка импульса
_NTO_TRACE_COMM_SPULSE_DEA SND_PULSE_DEA Отправка импульса _PULSE_CODE_COIDDEATH
_NTO_TRACE_COMM_SPULSE_DIS SND_PULSE_DIS Отправка импульса _PULSE_CODE_DISCONNECT
_NTO_TRACE_COMM_SPULSE_EXE SND_PULSE_EXE Отправка импульса SIGEV_PULSE
_NTO_TRACE_COMM_SPULSE_QUN SND_PULSE_QUN Отправка импульса _PULSE_CODE_NET_UNBLOCK
_NTO_TRACE_COMM_SPULSE_UN SND_PULSE_UN Отправка импульса _PULSE_CODE_UNBLOCK

Класс событий управления: _NTO_TRACE_CONTROL

Класс _NTO_TRACE_CONTROL включает в себя события, которые связаны с управлением трассировкой:

Событие Метка traceprinter Условие генерации события
_NTO_TRACE_CONTROLBUFFER BUFFER Диагностическое ядро начинает заполнять новый буфер
_NTO_TRACE_CONTROLTIME TIME 32 младших разряда 64-разрядных часов переполняются либо ядро генерирует событие _NTO_TRACE_CONTROLBUFFER

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

Класс событий обработки прерываний: _NTO_TRACE_INTENTER, _NTO_TRACE_INTEXIT, _NTO_TRACE_INT_HANDLER_ENTER и _NTO_TRACE_INT_HANDLER_EXIT

Эти классы используются для наблюдения за прерываниями:

Класс Метка traceprinter Условие генерации события
_NTO_TRACE_INTENTER INT_ENTR Начинается обработка прерывания
_NTO_TRACE_INTEXIT INT_EXIT Заканчивается обработка прерывания
_NTO_TRACE_INT_HANDLER_ENTER INT_HANDLER_ENTR Вход в обработчика прерывания
_NTO_TRACE_INT_HANDLER_EXIT INT_HANDLER_EXIT Выход из обработчика прерывания

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

INTR_ENTER
INTR_HANDLER_ENTER
INTR_HANDLER_EXIT
INTR_HANDLER_ENTER
INTR_HANDLER_EXIT
INT_EXIT

_NTO_TRACE_INT — псевдокласс, который включает в себя все классы прерываний.

«Событием» является номер вектора прерывания в диапазоне от _NTO_TRACE_INTFIRST до _NTO_TRACE_INTLAST.

Класс событий вызовов ядра: _NTO_TRACE_KERCALLENTER, _NTO_TRACE_KERCALLEXIT и _NTO_TRACE_KERCALLINT

Следующие классы используются для наблюдения за вызовами ядра:

_NTO_TRACE_KERCALL — псевдокласс, который включает в себя все указанные классы.

Метки traceprinter для этих классов: KER_CALL, KER_EXIT и INT_CALL, за которыми следует имя вызова ядра в верхнем регистре.

Большинство событий этих классов очевидным образом соответствуют вызовам ядра, а некоторые события — внутренним функциям:

Событие Вызов ядра
__KER_BAD Н/Д
__KER_CHANCON_ATTR ChannelConnectAttr()
__KER_CHANNEL_CREATE ChannelCreate()
__KER_CHANNEL_DESTROY ChannelDestroy()
__KER_CLOCK_ADJUST ClockAdjust()
__KER_CLOCK_ID ClockId()
__KER_CLOCK_PERIOD ClockPeriod()
__KER_CLOCK_TIME ClockTime()
__KER_CONNECT_ATTACH ConnectAttach()
__KER_CONNECT_CLIENT_INFO ConnectClientInfo()
__KER_CONNECT_DETACH ConnectDetach()
__KER_CONNECT_FLAGS ConnectFlags()
__KER_CONNECT_SERVER_INFO ConnectServerInfo()
__KER_INTERRUPT_ATTACH InterruptAttach()
__KER_INTERRUPT_DETACH InterruptDetach()
__KER_INTERRUPT_DETACH_FUNC Н/Д
__KER_INTERRUPT_MASK InterruptMask()
__KER_INTERRUPT_UNMASK InterruptUnmask()
__KER_INTERRUPT_WAIT InterruptWait()
__KER_MSG_CURRENT MsgCurrent()
__KER_MSG_DELIVER_EVENT MsgDeliverEvent()
__KER_MSG_ERROR MsgError()
__KER_MSG_INFO MsgInfo()
__KER_MSG_KEYDATA MsgKeyData()
__KER_MSG_READIOV MsgReadIov()
__KER_MSG_READV MsgRead(), MsgReadv()
__KER_MSG_READWRITEV Н/Д
__KER_MSG_RECEIVEPULSEV MsgReceivePulse(), MsgReceivePulsev()
__KER_MSG_RECEIVEV MsgReceive(), MsgReceivev()
__KER_MSG_REPLYV MsgReply(), MsgReplyv()
__KER_MSG_SENDV MsgSend(), MsgSendv() и MsgSendvs()
__KER_MSG_SENDVNC MsgSendnc(), MsgSendvnc() и MsgSendvsnc()
__KER_MSG_SEND_PULSE MsgSendPulse()
__KER_MSG_VERIFY_EVENT MsgVerifyEvent()
__KER_MSG_WRITEV MsgWrite(), MsgWritev()
__KER_NET_CRED NetCred()
__KER_NET_INFOSCOID NetInfoScoid()
__KER_NET_SIGNAL_KILL NetSignalKill()
__KER_NET_UNBLOCK NetUnblock()
__KER_NET_VTID NetVtid()
__KER_NOP Н/Д
__KER_SCHED_GET SchedGet()
__KER_SCHED_INFO SchedInfo()
__KER_SCHED_SET SchedSet()
__KER_SCHED_YIELD SchedYield()
__KER_SIGNAL_ACTION SignalAction()
__KER_SIGNAL_FAULT Н/Д
__KER_SIGNAL_KILL SignalKill()
__KER_SIGNAL_PROCMASK SignalProcmask()
__KER_SIGNAL_RETURN SignalReturn()
__KER_SIGNAL_SUSPEND SignalSuspend()
__KER_SIGNAL_WAITINFO SignalWaitInfo()
__KER_SYNC_CONDVAR_SIGNAL SyncCondvarSignal()
__KER_SYNC_CONDVAR_WAIT SyncCondvarWait()
__KER_SYNC_CREATE SyncCreate(), SyncTypeCreate()
__KER_SYNC_CTL SyncCtl()
__KER_SYNC_DESTROY SyncDestroy()
__KER_SYNC_MUTEX_LOCK SyncMutexLock()
__KER_SYNC_MUTEX_REVIVE SyncMutexRevive()
__KER_SYNC_MUTEX_UNLOCK SyncMutexUnlock()
__KER_SYNC_SEM_POST SyncSemPost()
__KER_SYNC_SEM_WAIT SyncSemWait()
__KER_SYS_CPUPAGE_GET Н/Д
__KER_THREAD_CANCEL ThreadCancel()
__KER_THREAD_CREATE ThreadCreate()
__KER_THREAD_CTL ThreadCtl()
__KER_THREAD_DESTROY ThreadDestroy()
__KER_THREAD_DESTROYALL Н/Д
__KER_THREAD_DETACH ThreadDetach()
__KER_THREAD_JOIN ThreadJoin()
__KER_TIMER_ALARM TimerAlarm()
__KER_TIMER_CREATE TimerCreate()
__KER_TIMER_DESTROY TimerDestroy()
__KER_TIMER_INFO TimerInfo()
__KER_TIMER_SETTIME TimerSettime()
__KER_TIMER_TIMEOUT TimerTimeout()
__KER_TRACE_EVENT TraceEvent()

Класс событий процессов: _NTO_TRACE_PROCESS

Класс _NTO_TRACE_PROCESS включает в себя события, которые связаны с созданием и уничтожением процессов:

Событие Метка traceprinter Условие генерации события
_NTO_TRACE_PROCCREATE PROCCREATE Создается процесс
_NTO_TRACE_PROCCREATE_NAME PROCCREATE_NAME Новому процессу присваивается имя
_NTO_TRACE_PROCDESTROY PROCDESTROY Уничтожается процесс
_NTO_TRACE_PROCDESTROY_NAME В настоящее время не используется
_NTO_TRACE_PROCTHREAD_NAME PROCTHREAD_NAME Потоку присваивается имя

Класс системных событий: _NTO_TRACE_SYSTEM

Класс _NTO_TRACE_SYSTEM включает в себя события, которые связаны с системой в целом:

Событие Метка traceprinter Условие генерации события
_NTO_TRACE_SYS_ADDRESS ADDRESS Достижение точки останова
_NTO_TRACE_SYS_APS_BNKR APS_BANKRUPTCY Адаптивная партиция исчерпала резервный бюджет
_NTO_TRACE_SYS_APS_BUDGETS APS_NEW_BUDGET Функция SchedCtl() вызывается с указанием команды SCHED_APS_CREATE_PARTITION или SCHED_APS_MODIFY_PARTITION. Это событие также генерируется автоматически, когда диспетчер адаптивного партиционирования сбрасывает резервный бюджет при банкротстве.
_NTO_TRACE_SYS_APS_NAME APS_NAME Функция SchedCtl() вызывается с указанием команды SCHED_APS_CREATE_PARTITION
_NTO_TRACE_SYS_COMPACTION COMPACTION Запускается алгоритм дефрагментации памяти compaction_minimal (см. Дефрагментация физической памяти)
_NTO_TRACE_SYS_FUNC_ENTER FUNC_ENTER Выполняется вход в функцию с диагностическим кодом для профилирования
_NTO_TRACE_SYS_FUNC_EXIT FUNC_EXIT Выполняется выход из функции с диагностическим кодом для профилирования
_NTO_TRACE_SYS_MAPNAME MAPNAME Вызывается функция dlopen()
_NTO_TRACE_SYS_MMAP MMAP Вызывается функция mmap() или mmap64()
_NTO_TRACE_SYS_MUNMAP MUNMAP Вызывается функция munmap()
_NTO_TRACE_SYS_PATHMGR PATHMGR_OPEN Выполняется операция с использованием путевого имени и вызовом функции connect библиотеки libc (например, open()). Функция connect отправляет сообщение модулю procnto, который разрешает путевое имя и определяет множество администраторов ресурсов, которые потенциально могут обработать его. Модуль procnto генерирует это событие после получения указанного сообщения.
_NTO_TRACE_SYS_SLOG SLOG Сообщение записывается в системный журнал

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

trace_func_enter()
Вставляет событие _NTO_TRACE_SYS_FUNC_ENTER для функции.
trace_func_exit()
Вставляет событие _NTO_TRACE_SYS_FUNC_EXIT для функции.
trace_here()
Вставляет событие _NTO_TRACE_SYS_ADDRESS для текущего адреса.

Класс событий потоков: _NTO_TRACE_THREAD

Класс _NTO_TRACE_THREAD включает в себя события, которые связаны с изменениями состояния потоков:

Событие Метка traceprinter Генерируется, когда поток
_NTO_TRACE_THCONDVAR THCONDVAR входит в состояние CONDVAR
_NTO_TRACE_THCREATE THCREATE создается
_NTO_TRACE_THDEAD THDEAD входит в состояние DEAD
_NTO_TRACE_THDESTROY THDESTROY уничтожается
_NTO_TRACE_THINTR THINTR входит в состояние INTERRUPT
_NTO_TRACE_THJOIN THJOIN входит в состояние JOIN
_NTO_TRACE_THMUTEX THMUTEX входит в состояние MUTEX
_NTO_TRACE_THNANOSLEEP THNANOSLEEP входит в состояние NANOSLEEP
_NTO_TRACE_THNET_REPLY THNET_REPLY входит в состояние NET_REPLY
_NTO_TRACE_THNET_SEND THNET_SEND входит в состояние NET_SEND
_NTO_TRACE_THREADY THREADY входит в состояние READY
_NTO_TRACE_THRECEIVE THRECEIVE входит в состояние RECEIVE
_NTO_TRACE_THREPLY THREPLY входит в состояние REPLY
_NTO_TRACE_THRUNNING THRUNNING входит в состояние RUNNING
_NTO_TRACE_THSEM THSEM входит в состояние SEM
_NTO_TRACE_THSEND THSEND входит в состояние SEND
_NTO_TRACE_THSIGSUSPEND THSIGSUSPEND входит в состояние SIGSUSPEND
_NTO_TRACE_THSIGWAITINFO THSIGWAITINFO входит в состояние SIGWAITINFO
_NTO_TRACE_THSTACK THSTACK входит в состояние STACK
_NTO_TRACE_THSTOPPED THSTOPPED входит в состояние STOPPED
_NTO_TRACE_THWAITCTX THWAITCTX входит в состояние WAITCTX
_NTO_TRACE_THWAITPAGE THWAITPAGE входит в состояние WAITPAGE
_NTO_TRACE_THWAITTHREAD THWAITTHREAD входит в состояние WAITTHREAD

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

Дополнительную информацию о состояниях потоков см. в разделе Жизненный цикл потока.

Пользовательский класс: _NTO_TRACE_USER

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

trace_logb()
Вставка составного трассировочного пользовательского события
trace_logf()
Вставка строкового пользовательского трассировочного события
trace_logi()
Вставка простого пользовательского трассировочного события
trace_nlogf()
Вставка строкового пользовательского трассировочного события с указанием максимальной длины строки
trace_vnlogf()
Вставка строкового пользовательского трассировочного события со списком из переменного количества аргументов

или вызов функции TraceEvent() с указанием одной из следующих команд:

Событие должно находиться в диапазоне от _NTO_TRACE_USERFIRST до _NTO_TRACE_USERLAST, но его смысл определяется разработчиком.

В утилите traceprinter этим событиям соответствует метка USREVENT. Эта метка следует за целочисленным типом события.

Класс событий виртуальных потоков: _NTO_TRACE_VTHREAD

Класс _NTO_TRACE_VTHREAD включает в себя события изменений состояния виртуальных потоков — специальных объектов, связанных с прозрачной распределенной обработкой по протоколу Qnet. В ядре часто хранятся указатели из различных структур данных на соответствующие потоки. Если поток находится на другом узле Qnet, ядро создает для него виртуальный объект вместо локального.

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

Событие Метка traceprinter Генерируется, когда виртуальный поток
_NTO_TRACE_VTHCONDVAR VTHCONDVAR входит в состояние CONDVAR
_NTO_TRACE_VTHCREATE VTHCREATE создается
_NTO_TRACE_VTHDEAD VTHDEAD входит в состояние DEAD
_NTO_TRACE_VTHDESTROY VTHDESTROY уничтожается
_NTO_TRACE_VTHINTR VTHINTR входит в состояние INTERRUPT
_NTO_TRACE_VTHJOIN VTHJOIN входит в состояние JOIN
_NTO_TRACE_VTHMUTEX VTHMUTEX входит в состояние MUTEX
_NTO_TRACE_VTHNANOSLEEP VTHNANOSLEEP входит в состояние NANOSLEEP
_NTO_TRACE_VTHNET_REPLY VTHNET_REPLY входит в состояние NET_REPLY
_NTO_TRACE_VTHNET_SEND VTHNET_SEND входит в состояние NET_SEND
_NTO_TRACE_VTHREADY VTHREADY входит в состояние READY
_NTO_TRACE_VTHRECEIVE VTHRECEIVE входит в состояние RECEIVE
_NTO_TRACE_VTHREPLY VTHREPLY входит в состояние REPLY
_NTO_TRACE_VTHRUNNING VTHRUNNING входит в состояние RUNNING
_NTO_TRACE_VTHSEM VTHSEM входит в состояние SEM
_NTO_TRACE_VTHSEND VTHSEND входит в состояние SEND
_NTO_TRACE_VTHSIGSUSPEND VTHSIGSUSPEND входит в состояние SIGSUSPEND
_NTO_TRACE_VTHSIGWAITINFO VTHSIGWAITINFO входит в состояние SIGWAITINFO
_NTO_TRACE_VTHSTACK VTHSTACK входит в состояние STACK
_NTO_TRACE_VTHSTOPPED VTHSTOPPED входит в состояние STOPPED
_NTO_TRACE_VTHWAITCTX VTHWAITCTX входит в состояние WAITCTX
_NTO_TRACE_VTHWAITPAGE VTHWAITPAGE входит в состояние WAITPAGE
_NTO_TRACE_VTHWAITTHREAD VTHWAITTHREAD входит в состояние WAITTHREAD




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