Концепция событий ядра при трассировке
В этой главе:
Микроядро ЗОСРВ «Нейтрино» генерирует события не только для системных вызовов, но и для других действий, в числе которых:
Диагностическая версия ядра также вставляет «искусственные» события:
Некоторые вызовы ядра и действия в системе могут приводить к генерации нескольких событий.
Процессы в ЗОСРВ «Нейтрино» могут состоять из множества потоков. Многопоточные приложения сложнее, чем однопоточные — операционная система должна обеспечивать выполнение конкурирующих друг с другом потоков, имеющих различные приоритеты.
В этом примере используются два потока:
Мы будем наблюдать за их выполнением, считая, что они запускаются одновременно:
![]() | Когда начинается ведение журнала, диагностическая версия ядра регистрирует в нем информацию о каждом потоке. Во время этой процедуры создаются существующие процессы. |
Время | Поток | Действие | Комментарий |
---|---|---|---|
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 | ... | ... | ... |
Переключение между потоками не происходит мгновенно. Когда один поток блокируется или добровольно уступает место другому, ядро должно сохранять настройки перед его запуском. Время сохранения состояния первого потока и восстановления состояния второго потока называется временем переключения контекста. Переключение контекста происходит быстро, однако важно учитывать его.
Иногда два или более потоков чередуются друг с другом, не выполняя полезной работы. Это похоже на двух чрезмерно вежливых людей, которые пытаются войти в одну дверь — каждый предлагает другому пройти первым, и в результате ни один из них не попадает внутрь вовремя (в аналогичной ситуации оказываются и два агрессивных человека). Инструменты системного анализа позволяют легко и быстро обнаруживать такие неполадки. Сопоставляя операции переключения контекста с изменениями состояния потоков, разработчик с легкостью определяет причины «зависания» систем, которые в остальное время работают быстро.
Для обеспечения максимальной скорости реакции значительная часть микроядра ЗОСРВ «Нейтрино» является полностью вытесняемой. Иногда вызов ядра, который прерывается во время выполнения потока, не возобновляется с момента прерывания, а «откатывается назад» и выполняется с начала. Инструменты системного анализа скрывают большинство «фиктивных» вызовов, однако пользователь может наблюдать несколько событий, сгенерированных вытесненными потоками. В таких случаях актуальным является последнее событие.
Большинство событий умещаются в одном элементе буфера событий и называются простыми событиями. Если событие содержит большое количество информации, оно размещается в нескольких элементах буфера и называется составным событием. Поскольку все элементы буфера событий одинаковы, программа сбора данных не проводит различий между ними.
Дополнительную информацию о простых и составных событиях см. в главе Интерпретация трассировочных данных.
Можно собирать данные событий в следующих режимах:
Как правило, в подробном режиме данные событий занимают в несколько раз больше места, чем в кратком.
![]() | В кратком режиме события содержат не просто «урезанную с конца» информацию подробного режима, а наиболее важные данные, которые помещаются в один элемент буфера. По этой причине первый элемент события в подробном и кратком режимах могут не совпадать. |
Можно назначать краткий и подробный режимы всем или некоторым классам, а также конкретным событиям определенного класса; таким образом, класс может включать в себя как краткие, так и подробные события. Настройка режима событий будет рассмотрена в главе Сбор трассировочных данных.
Различия в информации, которая генерируется в кратком и подробном режимах, описаны в статье Перечень поддерживаемых событий системной трассы.
Поскольку даже небольшая трассировка может включать в себя множество событий, для облегчения обработки они организованы в виде классов:
<sys/trace.h>
также определен класс _NTO_TRACE_EMPTY, однако он является «заглушкой» и на текущий момент не используется В следующих разделах перечислены события каждого класса с указанием условий их генерации и меток, которыми их маркируют утилита traceprinter.
Информация о данных каждого события указана в приложении Перечень поддерживаемых событий системной трассы.
Класс _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 включает в себя события, которые связаны с управлением трассировкой:
Событие | Метка traceprinter | Условие генерации события |
---|---|---|
_NTO_TRACE_CONTROLBUFFER | BUFFER | Диагностическое ядро начинает заполнять новый буфер |
_NTO_TRACE_CONTROLTIME | TIME | 32 младших разряда 64-разрядных часов переполняются либо ядро генерирует событие _NTO_TRACE_CONTROLBUFFER |
С помощью событий _NTO_TRACE_CONTROLBUFFER утилита tracelogger проверяют наличие отброшенных буферов. В этот же момент диагностическое ядро генерирует событие _NTO_TRACE_CONTROLTIME, чтобы синхронизировать интегрированную среду разработки (если в отброшенном буфере находилось событие _NTO_TRACE_CONTROLTIME, которое указывает на переполнение часов).
Эти классы используются для наблюдения за прерываниями:
Класс | Метка 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_ENTERINTR_HANDLER_ENTERINTR_HANDLER_EXITINTR_HANDLER_ENTERINTR_HANDLER_EXITINT_EXIT
_NTO_TRACE_INT — псевдокласс, который включает в себя все классы прерываний.
«Событием» является номер вектора прерывания в диапазоне от _NTO_TRACE_INTFIRST до _NTO_TRACE_INTLAST.
Следующие классы используются для наблюдения за вызовами ядра:
EINTR
, в журнале также регистрируется событие _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 включает в себя события, которые связаны с созданием и уничтожением процессов:
Событие | Метка 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 включает в себя события, которые связаны с системой в целом:
Событие | Метка 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 | Сообщение записывается в системный журнал |
Для вставки системных событий в трассировочные данные можно использовать следующие вспомогательные функции:
Класс _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 включает в себя пользовательские события, которые создаются программой с помощью следующих вспомогательных функций:
или вызов функции TraceEvent() с указанием одной из следующих команд:
![]() | Аргумент команды _NTO_TRACE_INSERTCUSEREVENT содержит количество целых чисел (не байт) в переданном буфере. |
Событие должно находиться в диапазоне от _NTO_TRACE_USERFIRST до _NTO_TRACE_USERLAST, но его смысл определяется разработчиком.
В утилите traceprinter этим событиям соответствует метка USREVENT. Эта метка следует за целочисленным типом события.
Класс _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 |
Предыдущий раздел: перейти