Примеры фильтрации трассировочных данных
В этой главе рассматривается практика управления трассировкой событий с помощью функции TraceEvent():
Общий порядок применения каждого из приведенных руководств выглядит следующим образом:
.c.
Поcкольку по умолчанию используются 32 буфера, создаваемый файл трассировки имеет весьма большой объем; чтобы сократить его, мы уменьшим количество буферов при помощи ключа -n. Можно смело использовать значение по умолчанию, но учитывая, что файл будет большим.
Если вы не желаете запускать программу, изучите наши результаты утилиты traceprinter (имейте в виду, что эти результаты могут незначительно варьироваться в зависимости от версии утилиты и используемой системы).
Во избежание дублирования кода и повышения его наглядности мы разместили некоторые функции программ в заголовочном файле common.h:
/* common.h */#ifndef __COMMON_H_INCLUDED#define __COMMON_H_INCLUDED#include <errno.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <sys/trace.h>/* Контроль статуса выполнения TraceEvent() */#define CHECK( program, retval ) \if ( retval == -1 ) { \fprintf( stderr, "%s: %s():%d - call TraceEvent() failed (errno:%d, message:%s)\n", \program, __FUNCTION__, __LINE__, errno, strerror( errno ) ); \return (-1); \}/* Отключаем все фильтры, поскольку их текущее состояние заранее неизвестно */#define INIT( program ) \CHECK( program, TraceEvent( _NTO_TRACE_DELALLCLASSES ) ); \CHECK( program, TraceEvent( _NTO_TRACE_CLRCLASSPID, _NTO_TRACE_KERCALL ) ); \CHECK( program, TraceEvent( _NTO_TRACE_CLRCLASSTID, _NTO_TRACE_KERCALL ) ); \CHECK( program, TraceEvent( _NTO_TRACE_CLRCLASSPID, _NTO_TRACE_THREAD ) ); \CHECK( program, TraceEvent( _NTO_TRACE_CLRCLASSTID, _NTO_TRACE_THREAD ) );#endif /* __COMMON_H_INCLUDED */
Для компиляции программ необходимо поместить файл common.h
в каталог, где находится C-код.
В первом примере мы настроим режим демона для сбора всех событий всех классов. Ниже приведен исходный код программы all_classes.c
.
Пример иллюстрирует основы использования вызова ядра TraceEvent() и диагностического модуля с утилитой tracelogger в режиме демона. В мониторинге участвуют все классы и события, которые входят в их состав. Для использования этого примера запустите утилиту tracelogger в режиме демона:
tracelogger -n количество_итераций -d1
где количество_итераций - число от 1 до 10. После запуска этого примера утилита tracelogger зарегистрирует указанное количество итераций и завершит работу. При успешном завершении примера не печатаются никакие сообщения. Собранные события можно просматривать с помощью утилиты traceprinter. Дополнительную информацию см. в сопроводительной документации и комментариях в исходном коде.
#include "common.h"int main( int argc, char **argv ){/* Отключаем все фильтры, поскольку их текущее состояние заранее неизвестно */INIT( argv[0] );/* Задаем режим генерации кратких событий всех классов */CHECK( argv[0], TraceEvent( _NTO_TRACE_SETALLCLASSESFAST ) );/* Сбор событий всех классов */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDALLCLASSES ) );/* Запуск процесса трассировки. В процессе трассировки демон tracelogger регистрирует* все события. При его запуске можно задать количество итераций (т.е. буферов ядра,* в которых регистрируются события). */CHECK( argv[0], TraceEvent( _NTO_TRACE_START ) );/* Утилита tracelogger продолжит выполнение до регистрации указанного количества событий */return (0);}
Скомпилируйте программу и запустите утилиту tracelogger:
tracelogger -d1 -n 3 -f all_classes.kev
Запустите в другом окне:
./all_classes
Несмотря на то, что программа быстро завершила работу, она сгенерировала огромное количество данных. Трассировочные данные находятся в файле all_classes.kev
. Чтобы изучить его, введите команду:
traceprinter -f all_classes.kev | less
Результаты утилиты traceprinter выглядят следующим образом:
TRACEPRINTER version 1.02TRACEPARSER LIBRARY version 1.02-- HEADER FILE INFORMATION --TRACE_FILE_NAME:: all_classes.kevTRACE_DATE:: Wed Jun 24 10:52:58 2009TRACE_VER_MAJOR:: 1TRACE_VER_MINOR:: 01TRACE_LITTLE_ENDIAN:: TRUETRACE_ENCODING:: 16 byte eventsTRACE_BOOT_DATE:: Tue Jun 23 11:47:46 2009TRACE_CYCLES_PER_SEC:: 736629000TRACE_CPU_NUM:: 1TRACE_SYSNAME:: QNXTRACE_NODENAME:: localhostTRACE_SYS_RELEASE:: 6.4.1TRACE_SYS_VERSION:: 2009/05/20-17:35:56EDTTRACE_MACHINE:: x86pcTRACE_SYSPAGE_LEN:: 2264TRACE_TRACELOGGER_ARGS:: tracelogger -d1 -n 3 -f all_classes.kev-- KERNEL EVENTS --t:0x4f81e320 CPU:00 CONTROL: BUFFER sequence = 33, num_events = 714t:0x4f81e320 CPU:00 CONTROL :TIME msb:0x000037b0 lsb(offset):0x4f81e014t:0x4f82017a CPU:00 PROCESS :PROCCREATE_NAMEppid:0pid:1name:proc/boot/procnto-smp-instr...t:0x4f854048 CPU:00 THREAD :THCREATE pid:1511472 tid:1t:0x4f854140 CPU:00 THREAD :THRUNNING pid:1511472 tid:1t:0x4f854910 CPU:00 KER_EXIT:TRACE_EVENT/01 ret_val:0x00000000 empty:0x00000000t:0x4f856aac CPU:00 KER_CALL:THREAD_DESTROY/47 tid:-1 status_p:0t:0x4f857dca CPU:00 KER_EXIT:THREAD_DESTROY/47 ret_val:0x00000030 empty:0x00000000t:0x4f8588d3 CPU:00 KER_CALL:THREAD_DESTROYALL/48 empty:0x00000000 empty:0x00000000t:0x4f858ed7 CPU:00 THREAD :THDESTROY pid:1511472 tid:1t:0x4f8598b9 CPU:00 THREAD :THDEAD pid:1511472 tid:1t:0x4f859c4c CPU:00 THREAD :THRUNNING pid:1 tid:1t:0x4f85c6e3 CPU:00 COMM :SND_PULSE_EXE scoid:0x40000002 pid:1t:0x4f85cecd CPU:00 THREAD :THRUNNING pid:1 tid:12t:0x4f85d5ad CPU:00 THREAD :THREADY pid:1 tid:1t:0x4f85e5b3 CPU:00 COMM :REC_PULSE scoid:0x40000002 pid:1t:0x4f860ee2 CPU:00 KER_CALL:THREAD_CREATE/46 func_p:f0023170 arg_p:eff6e000t:0x4f8624c7 CPU:00 THREAD :THCREATE pid:1511472 tid:1t:0x4f8625ff CPU:00 THREAD :THWAITTHREAD pid:1 tid:12t:0x4f8627b4 CPU:00 THREAD :THRUNNING pid:1511472 tid:1t:0x4f8636fd CPU:00 THREAD :THREADY pid:1 tid:12t:0x4f865c34 CPU:00 KER_CALL:CONNECT_SERVER_INFO/41 pid:0 coid:0x00000000t:0x4f866836 CPU:00 KER_EXIT:CONNECT_SERVER_INFO/41 coid:0x00000000 info->nd:0t:0x4f86735e CPU:00 KER_CALL:TIMER_TIMEOUT/75 timeout_flags:0x00000050 ntime(sec):30t:0x4f868445 CPU:00 KER_EXIT:TIMER_TIMEOUT/75 prev_timeout_flags:0x00000000 otime(sec):0t:0x4f8697d3 CPU:00 INT_ENTR:0x00000000 (0) IP:0xf008433et:0x4f86a276 CPU:00 INT_HANDLER_ENTR:0x00000000 (0) PID:126997 IP:0x080b7334 AREA:0x0812a060t:0x4f86afa7 CPU:00 INT_HANDLER_EXIT:0x00000000 (0) SIGEVENT:NONEt:0x4f86b304 CPU:00 INT_HANDLER_ENTR:0x00000000 (0) PID:1 IP:0xf0056570 AREA:0x00000000t:0x4f86ca12 CPU:00 INT_HANDLER_EXIT:0x00000000 (0) SIGEVENT:NONEt:0x4f86cff6 CPU:00 INT_EXIT:0x00000000 (0) inkernel:0x00000f01t:0x4f86e276 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000000 msg:"" (0x00040116)t:0x4f86e756 CPU:00 COMM :SND_MESSAGE rcvid:0x0000004f pid:159762t:0x4f86f84a CPU:00 THREAD :THREPLY pid:1511472 tid:1t:0x4f8705dd CPU:00 THREAD :THREADY pid:159762 tid:1t:0x4f8707d4 CPU:00 THREAD :THRUNNING pid:159762 tid:1t:0x4f870bff CPU:00 COMM :REC_MESSAGE rcvid:0x0000004f pid:159762t:0x4f878b6c CPU:00 KER_CALL:MSG_REPLYV/15 rcvid:0x0000004f status:0x00000000t:0x4f878f4b CPU:00 COMM :REPLY_MESSAGE tid:1 pid:1511472t:0x4f8798d2 CPU:00 THREAD :THREADY pid:1511472 tid:1t:0x4f879db8 CPU:00 KER_EXIT:MSG_REPLYV/15 ret_val:0 empty:0x00000000t:0x4f87a84f CPU:00 KER_CALL:MSG_RECEIVEV/14 chid:0x00000001 rparts:1...
В этом примере демонстрируется способность трассировочного модуля собирать гигантские объемы данных о событиях. Первая часть трассировочных данных включает в себя сведения о начальном состоянии всех выполняемых процессов; чтобы отключить сбор этих данных, следует запускать трассировку с флагом _NTO_TRACE_STARTNOSTATE вместо _NTO_TRACE_START.
Полезно уметь собирать все возможные данные, однако иногда необходимо сужать критерии поиска.
Теперь мы соберем все события одного класса _NTO_TRACE_THREAD. Он произвольно выбран для демонстрации фильтрации по классам и принципиально ничем не отличается от других классов. Полный список классов см. в разделе Классы и события. Ниже приведен исходный код программы one_class.c
.
Пример иллюстрирует основы использования вызова ядра TraceEvent() и диагностического модуля с утилитой tracelogger в режиме демона. Выполняется мониторинг (сбор) только событий класса потоков ( _NTO_TRACE_THREAD). Для использования этого примера запустите утилиту tracelogger в режиме демона:
tracelogger -n количество_итераций -d1
где количество_итераций - число от 1 до 10. После запуска этого примера утилита tracelogger зарегистрирует указанное количество итераций и завершит работу. При успешном завершении примера не печатаются никакие сообщения. Собранные события можно просматривать с помощью утилиты traceprinter.
#include "common.h"int main( int argc, char **argv ){/* Отключаем все фильтры, поскольку их текущее состояние заранее неизвестно */INIT( argv[0] );/* Сбор только событий класса "Поток" */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDCLASS, _NTO_TRACE_THREAD ) );/* Запуск процесса трассировки. В процессе трассировки демон tracelogger регистрирует* все события. При его запуске можно задать количество итераций (т.е. буферов ядра,* в которых регистрируются события). */CHECK( argv[0], TraceEvent( _NTO_TRACE_START ) );/* Утилита tracelogger продолжит выполнение до регистрации указанного количества событий */return (0);}
Скомпилируйте программу и запустите утилиту tracelogger:
tracelogger -d1 -n 3 -f one_class.kev
Запустите в другом окне:
./one_class
Трассировочные данные находятся в файле one_class.kev
. Чтобы изучить его, введите команду:
traceprinter -f one_class.kev | less
Результаты утилиты traceprinter выглядят следующим образом:
TRACEPRINTER version 1.02TRACEPARSER LIBRARY version 1.02-- HEADER FILE INFORMATION --TRACE_FILE_NAME:: one_class.kevTRACE_DATE:: Wed Jun 24 10:55:05 2009TRACE_VER_MAJOR:: 1TRACE_VER_MINOR:: 01TRACE_LITTLE_ENDIAN:: TRUETRACE_ENCODING:: 16 byte eventsTRACE_BOOT_DATE:: Tue Jun 23 11:47:46 2009TRACE_CYCLES_PER_SEC:: 736629000TRACE_CPU_NUM:: 1TRACE_SYSNAME:: QNXTRACE_NODENAME:: localhostTRACE_SYS_RELEASE:: 6.4.1TRACE_SYS_VERSION:: 2009/05/20-17:35:56EDTTRACE_MACHINE:: x86pcTRACE_SYSPAGE_LEN:: 2264TRACE_TRACELOGGER_ARGS:: tracelogger -d1 -n 3 -f one_class.kev-- KERNEL EVENTS --t:0x002c4d55 CPU:00 CONTROL: BUFFER sequence = 37, num_events = 714t:0x002c4d55 CPU:00 THREAD :THCREATE pid:1 tid:1t:0x002c5531 CPU:00 THREAD :THREADY pid:1 tid:1 priority:0 policy:1t:0x002c5bbe CPU:00 THREAD :THCREATE pid:1 tid:2t:0x002c5cd2 CPU:00 THREAD :THRECEIVE pid:1 tid:2 priority:255 policy:2t:0x002c6185 CPU:00 THREAD :THCREATE pid:1 tid:3t:0x002c6272 CPU:00 THREAD :THRECEIVE pid:1 tid:3 priority:255 policy:2t:0x002c64eb CPU:00 THREAD :THCREATE pid:1 tid:4t:0x002c65d8 CPU:00 THREAD :THRECEIVE pid:1 tid:4 priority:10 policy:2t:0x002c67fc CPU:00 THREAD :THCREATE pid:1 tid:5t:0x002c68ea CPU:00 THREAD :THRECEIVE pid:1 tid:5 priority:255 policy:2t:0x002c6bae CPU:00 THREAD :THCREATE pid:1 tid:7t:0x002c6c9b CPU:00 THREAD :THRECEIVE pid:1 tid:7 priority:10 policy:2t:0x002c6f03 CPU:00 THREAD :THCREATE pid:1 tid:8t:0x002c6ff0 CPU:00 THREAD :THRECEIVE pid:1 tid:8 priority:10 policy:2t:0x002c72ec CPU:00 THREAD :THCREATE pid:1 tid:10t:0x002c73d9 CPU:00 THREAD :THRECEIVE pid:1 tid:10 priority:10 policy:2t:0x002c7665 CPU:00 THREAD :THCREATE pid:1 tid:11t:0x002c7752 CPU:00 THREAD :THRECEIVE pid:1 tid:11 priority:10 policy:2t:0x002c7a9d CPU:00 THREAD :THCREATE pid:1 tid:12t:0x002c7b8a CPU:00 THREAD :THRECEIVE pid:1 tid:12 priority:10 policy:2t:0x002c7e44 CPU:00 THREAD :THCREATE pid:1 tid:15t:0x002c7f31 CPU:00 THREAD :THRECEIVE pid:1 tid:15 priority:10 policy:2t:0x002c81a2 CPU:00 THREAD :THCREATE pid:1 tid:20t:0x002c828f CPU:00 THREAD :THRECEIVE pid:1 tid:20 priority:10 policy:2t:0x002c88e3 CPU:00 THREAD :THCREATE pid:2 tid:1t:0x002c89d3 CPU:00 THREAD :THREPLY pid:2 tid:1 priority:10 policy:3t:0x002c8fad CPU:00 THREAD :THCREATE pid:4099 tid:1t:0x002c909a CPU:00 THREAD :THRECEIVE pid:4099 tid:1 priority:10 policy:3t:0x002c95b7 CPU:00 THREAD :THCREATE pid:4100 tid:1t:0x002c96a4 CPU:00 THREAD :THRECEIVE pid:4100 tid:1 priority:10 policy:3t:0x002c9b6e CPU:00 THREAD :THCREATE pid:4101 tid:1t:0x002c9ccd CPU:00 THREAD :THSIGWAITINFO pid:4101 tid:1 priority:10 policy:3...
Обратите внимание, что количество отображаемых результатов значительно уменьшилось.
В предыдущем разделе мы рассмотрели сбор событий определенного класса. Теперь мы можем дополнительно сузить критерии поиска и настроить сбор пяти отдельных событий из четырех классов. Ниже приведен исходный код программы five_events.c
.
Пример иллюстрирует основы использования вызова ядра TraceEvent() и диагностического модуля с утилитой tracelogger в режиме демона. В мониторинге участвуют только пять событий из четырех классов. События класса _NTO_TRACE_KERCALL регистрируются в подробном режиме. Для использования этого примера запустите утилиту tracelogger в режиме демона:
tracelogger -n количество_итераций -d1
где количество_итераций - число от 1 до 10. После запуска этого примера утилита tracelogger зарегистрирует указанное количество итераций и завершит работу. При успешном завершении примера не печатаются никакие сообщения. Собранные события можно просматривать с помощью утилиты traceprinter.
#include <sys/kercalls.h>#include "common.h"int main(int argc, char **argv){/* Отключаем все фильтры, поскольку их текущее состояние заранее неизвестно */INIT( argv[0] );/* Установка подробного режима сбора событий */CHECK(argv[0], TraceEvent(_NTO_TRACE_SETALLCLASSESWIDE));/** Сбор двух событий класса _NTO_TRACE_THREAD*/CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_THREAD, _NTO_TRACE_THRUNNING ) );CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_THREAD, _NTO_TRACE_THCREATE ) );/* Сбор одного события класса _NTO_TRACE_PROCESS */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_PROCESS, _NTO_TRACE_PROCCREATE_NAME ) );/* Сбор одного события класса _NTO_TRACE_INTENTER */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_INTENTER, _NTO_TRACE_INTFIRST ) );/* Сбор одного события класса _NTO_TRACE_KERCALLEXIT, события __KER_MSG_READV. */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_KERCALLEXIT, __KER_MSG_READV ) );/* Запуск процесса трассировки. В процессе трассировки демон tracelogger регистрирует* все события. При его запуске можно задать количество итераций (т.е. буферов ядра,* в которых регистрируются события). */CHECK( argv[0], TraceEvent( _NTO_TRACE_START ) );/* Утилита tracelogger продолжит выполнение до регистрации указанного количества событий */return (0);}
Скомпилируйте программу и запустите утилиту tracelogger:
tracelogger -d1 -n 3 -f five_events.kev
Запустите в другом окне:
./five_events
Трассировочные данные находятся в файле five_events.kev
. Чтобы изучить его, введите команду:
traceprinter -f five_events.kev | less
Результаты утилиты traceprinter выглядят следующим образом:
TRACEPRINTER version 1.02TRACEPARSER LIBRARY version 1.02-- HEADER FILE INFORMATION --TRACE_FILE_NAME:: five_events.kevTRACE_DATE:: Wed Jun 24 10:56:04 2009TRACE_VER_MAJOR:: 1TRACE_VER_MINOR:: 01TRACE_LITTLE_ENDIAN:: TRUETRACE_ENCODING:: 16 byte eventsTRACE_BOOT_DATE:: Tue Jun 23 11:47:46 2009TRACE_CYCLES_PER_SEC:: 736629000TRACE_CPU_NUM:: 1TRACE_SYSNAME:: QNXTRACE_NODENAME:: localhostTRACE_SYS_RELEASE:: 6.4.1TRACE_SYS_VERSION:: 2009/05/20-17:35:56EDTTRACE_MACHINE:: x86pcTRACE_SYSPAGE_LEN:: 2264TRACE_TRACELOGGER_ARGS:: tracelogger -d1 -n 3 -f five_events.kev-- KERNEL EVENTS --t:0x1a14da34 CPU:00 CONTROL: BUFFER sequence = 41, num_events = 714t:0x1a14da34 CPU:00 PROCESS :PROCCREATE_NAMEppid:0pid:1name:proc/boot/procnto-smp-instrt:0x1a14ea7d CPU:00 THREAD :THCREATE pid:1 tid:1t:0x1a14ed04 CPU:00 THREAD :THCREATE pid:1 tid:2...t:0x1a1cc345 CPU:00 THREAD :THRUNNING pid:1 tid:15 priority:10 policy:2t:0x1a1d01b9 CPU:00 THREAD :THRUNNING pid:8200 tid:5 priority:10 policy:3t:0x1a1d6424 CPU:00 INT_ENTR:0x00000000 (0) IP:0xb8229890t:0x1a1ed261 CPU:00 THREAD :THRUNNING pid:1 tid:4 priority:10 policy:2t:0x1a1f0016 CPU:00 THREAD :THRUNNING pid:426022 tid:1 priority:10 policy:2...t:0x2e77ebc5 CPU:00 THREAD :THRUNNING pid:1613871 tid:1 priority:10 policy:2t:0x2e78598d CPU:00 THREAD :THRUNNING pid:8200 tid:5 priority:10 policy:3t:0x2e7ac4fc CPU:00 INT_ENTR:0x00000000 (0) IP:0xb8229f61t:0x2e7cec3b CPU:00 KER_EXIT:MSG_READV/16rbytes:22540rmsg:"" (0x1a15080f 0x6e696273 0x6e69742f)t:0x2e7da478 CPU:00 THREAD :THRUNNING pid:1003562 tid:1 priority:10 policy:2t:0x2e7dc288 CPU:00 THREAD :THRUNNING pid:1 tid:15 priority:10 policy:2...
Теперь мы выборочно трассируем события и значительно уменьшаем объем генерируемых данных.
Возможно, вызовы ядра следует считать самым важным классом вызовов. В этом примере демонстрируется не только фильтрация, но и аргументы, принимаемые диагностической версией ядра. В простейшем виде эта программа аналогична программе one_class.c
, в которой выполнялся сбор событий одного класса. Ниже приведен исходный код программы ker_calls.c
.
Пример иллюстрирует основы использования вызова ядра TraceEvent() и диагностического модуля с утилитой tracelogger в режиме демона. Выполняется сбор состояний всех потоков и всех вызовов ядра либо одного вызова с заданным номером. Сбор вызовов ядра осуществляется в подробном режиме. Параметр программы -n num позволяет задать номер регистрируемого вызова ядра (по умолчанию выполняется сбор всех вызовов ядра). Для использования этого примера запустите утилиту tracelogger в режиме демона:
tracelogger -n количество_итераций -d1
где количество_итераций - число от 1 до 10. После запуска этого примера утилита tracelogger зарегистрирует указанное количество итераций и завершит работу. При успешном завершении примера не печатаются никакие сообщения. Собранные события можно просматривать с помощью утилиты traceprinter.
#include "common.h"int main(int argc, char **argv){int arg_var; /* для анализа введенных аргументов */int call_num=(-1); /* номер регистрируемого вызова ядра *//* Анализ командно-строковых аргументов - определение номера вызова ядра */while ( (arg_var = getopt( argc, argv, "n:" )) != (-1) ){switch ( arg_var ){case 'n':call_num = strtoul( optarg, NULL, 10 );break;default:fprintf( stderr, "%s: %s\n", argv[0], "error parsing command-line arguments - exiting" );return (-1);}}/* Отключаем все фильтры, поскольку их текущее состояние заранее неизвестно */INIT( argv[0] );/* Установка режима генерации подробных событий всех классов */CHECK( argv[0], TraceEvent( _NTO_TRACE_SETALLCLASSESWIDE ) );/* Сбор событий класса _NTO_TRACE_THREAD. Они нужны нам для определения состояния активного потока. */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDCLASS, _NTO_TRACE_THREAD ) );/* Добавление всех или одного вызова ядра */if ( call_num != (-1) ){CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_KERCALL, call_num ) );} else {CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDCLASS, _NTO_TRACE_KERCALL ) );}/* Запуск процесса трассировки. В процессе трассировки демон tracelogger регистрирует* все события. При его запуске можно задать количество итераций (т.е. буферов ядра,* в которых регистрируются события). */CHECK( argv[0], TraceEvent( _NTO_TRACE_START ) );/* Утилита tracelogger продолжит выполнение до регистрации указанного количества событий */return (0);}
Скомпилируйте программу и запустите утилиту tracelogger:
tracelogger -d1 -n 3 -f ker_calls.all.kev
Запустите в другом окне:
./ker_calls
Трассировочные данные находятся в файле ker_calls.all.kev
. Чтобы изучить его, введите команду:
traceprinter -f ker_calls.all.kev | less
Результаты утилиты traceprinter выглядят следующим образом:
TRACEPRINTER version 1.02TRACEPARSER LIBRARY version 1.02-- HEADER FILE INFORMATION --TRACE_FILE_NAME:: ker_calls.all.kevTRACE_DATE:: Wed Jun 24 10:57:01 2009TRACE_VER_MAJOR:: 1TRACE_VER_MINOR:: 01TRACE_LITTLE_ENDIAN:: TRUETRACE_ENCODING:: 16 byte eventsTRACE_BOOT_DATE:: Tue Jun 23 11:47:46 2009TRACE_CYCLES_PER_SEC:: 736629000TRACE_CPU_NUM:: 1TRACE_SYSNAME:: QNXTRACE_NODENAME:: localhostTRACE_SYS_RELEASE:: 6.4.1TRACE_SYS_VERSION:: 2009/05/20-17:35:56EDTTRACE_MACHINE:: x86pcTRACE_SYSPAGE_LEN:: 2264TRACE_TRACELOGGER_ARGS:: tracelogger -d1 -n 3 -f ker_calls.all.kev-- KERNEL EVENTS --t:0x463ad541 CPU:00 CONTROL: BUFFER sequence = 45, num_events = 714t:0x463ad541 CPU:00 THREAD :THCREATE pid:1 tid:1t:0x463adbe1 CPU:00 THREAD :THREADY pid:1 tid:1 priority:0 policy:1t:0x463adfa8 CPU:00 THREAD :THCREATE pid:1 tid:2t:0x463ae098 CPU:00 THREAD :THRECEIVE pid:1 tid:2 priority:255 policy:2t:0x463ae375 CPU:00 THREAD :THCREATE pid:1 tid:3...t:0x463d59b6 CPU:00 THREAD :THSIGWAITINFO pid:1658927 tid:2 priority:10 policy:2t:0x463d5cb2 CPU:00 THREAD :THCREATE pid:1663024 tid:1t:0x463d5da7 CPU:00 THREAD :THRUNNING pid:1663024 tid:1 priority:10 policy:2t:0x463d666e CPU:00 KER_EXIT:TRACE_EVENT/01 ret_val:0x00000000 empty:0x00000000t:0x463d8e65 CPU:00 KER_CALL:THREAD_DESTROY/47tid:-1priority:-1status_p:0t:0x463da615 CPU:00 KER_EXIT:THREAD_DESTROY/47 ret_val:0x00000030 empty:0x00000000t:0x463daf0a CPU:00 KER_CALL:THREAD_DESTROYALL/48 empty:0x00000000 empty:0x00000000t:0x463db531 CPU:00 THREAD :THDESTROY pid:1663024 tid:1t:0x463dc114 CPU:00 THREAD :THDEAD pid:1663024 tid:1 priority:10 policy:2t:0x463dc546 CPU:00 THREAD :THRUNNING pid:1 tid:1 priority:0 policy:1t:0x463df45d CPU:00 THREAD :THRUNNING pid:1 tid:4 priority:10 policy:2t:0x463dfa7f CPU:00 THREAD :THREADY pid:1 tid:1 priority:0 policy:1t:0x463e36b4 CPU:00 KER_CALL:THREAD_CREATE/46pid:1663024func_p:f0023170arg_p:eff4e000flags:0x00000000stacksize:10116stackaddr_p:eff4e264exitfunc_p:0policy:0sched_priority:0sched_curpriority:0param.__ss_low_priority:0param.__ss_max_repl:0param.__ss_repl_period.tv_sec:0param.__ss_repl_period.tv_nsec:0param.__ss_init_budget.tv_sec:0param.__ss_init_budget.tv_nsec:0param.empty:0guardsize:0empty:0t:0x463e50b0 CPU:00 THREAD :THCREATE pid:1663024 tid:1t:0x463e51d0 CPU:00 THREAD :THWAITTHREAD pid:1 tid:4 priority:10 policy:2t:0x463e5488 CPU:00 THREAD :THRUNNING pid:1663024 tid:1 priority:10 policy:2t:0x463e6408 CPU:00 THREAD :THREADY pid:1 tid:4 priority:10 policy:2...
Программа ker_calls.c
принимает аргумент -n, который позволяет наблюдать только за одним типом вызовов ядра. Выполним эту программу еще раз и укажем номер 14, которому соответствует __KER_MSG_RECEIVE
. Полный список значений аргумента -n см. в заголовочном файле <sys/kercalls.h>
.
Скомпилируйте программу и запустите утилиту tracelogger:
tracelogger -d1 -n 3 -f ker_calls.14.kev
Запустите в другом окне:
./ker_calls -n 14
Трассировочные данные находятся в файле ker_calls.14.kev
. Чтобы изучить его, введите команду:
traceprinter -f ker_calls.14.kev | less
Результаты утилиты traceprinter выглядят следующим образом:
TRACEPRINTER version 1.02TRACEPARSER LIBRARY version 1.02-- HEADER FILE INFORMATION --TRACE_FILE_NAME:: ker_calls.14.kevTRACE_DATE:: Wed Jun 24 13:39:20 2009TRACE_VER_MAJOR:: 1TRACE_VER_MINOR:: 01TRACE_LITTLE_ENDIAN:: TRUETRACE_ENCODING:: 16 byte eventsTRACE_BOOT_DATE:: Tue Jun 23 11:47:46 2009TRACE_CYCLES_PER_SEC:: 736629000TRACE_CPU_NUM:: 1TRACE_SYSNAME:: QNXTRACE_NODENAME:: localhostTRACE_SYS_RELEASE:: 6.4.1TRACE_SYS_VERSION:: 2009/05/20-17:35:56EDTTRACE_MACHINE:: x86pcTRACE_SYSPAGE_LEN:: 2264TRACE_TRACELOGGER_ARGS:: tracelogger -d1 -n 3 -f ker_calls.14.kev-- KERNEL EVENTS --t:0x73bf28d0 CPU:00 CONTROL: BUFFER sequence = 62, num_events = 714t:0x73bf28d0 CPU:00 THREAD :THCREATE pid:1 tid:1t:0x73bf2e16 CPU:00 THREAD :THREADY pid:1 tid:1 priority:0 policy:1t:0x73bf3203 CPU:00 THREAD :THCREATE pid:1 tid:2...t:0x73c21746 CPU:00 THREAD :THRUNNING pid:1 tid:1 priority:0 policy:1t:0x73c24352 CPU:00 THREAD :THRUNNING pid:1 tid:15 priority:10 policy:2t:0x73c247e0 CPU:00 THREAD :THREADY pid:1 tid:1 priority:0 policy:1t:0x73c2547b CPU:00 KER_EXIT:MSG_RECEIVEV/14rcvid:0x00000000rmsg:"" (0x00000000 0x00000081 0x001dd030)info->nd:0info->srcnd:0info->pid:1953840info->tid:1info->chid:1info->scoid:1073741874info->coid:1073741824info->msglen:0info->srcmsglen:56info->dstmsglen:24info->priority:10info->flags:0info->reserved:0t:0x73c29270 CPU:00 THREAD :THCREATE pid:1953840 tid:1t:0x73c293ca CPU:00 THREAD :THWAITTHREAD pid:1 tid:15 priority:10 policy:2t:0x73c2964a CPU:00 THREAD :THRUNNING pid:1953840 tid:1 priority:10 policy:2t:0x73c2a36c CPU:00 THREAD :THREADY pid:1 tid:15 priority:10 policy:2t:0x73c2fccc CPU:00 THREAD :THREPLY pid:1953840 tid:1 priority:10 policy:2t:0x73c30f6b CPU:00 THREAD :THREADY pid:159762 tid:1 priority:10 policy:3t:0x73c311b0 CPU:00 THREAD :THRUNNING pid:159762 tid:1 priority:10 policy:3t:0x73c31835 CPU:00 KER_EXIT:MSG_RECEIVEV/14rcvid:0x0000004frmsg:"" (0x00040116 0x00000000 0x00000004)info->nd:0info->srcnd:0info->pid:1953840info->tid:1info->chid:1info->scoid:1073741903info->coid:0info->msglen:4info->srcmsglen:4info->dstmsglen:0info->priority:10info->flags:0info->reserved:0t:0x73c3a359 CPU:00 THREAD :THREADY pid:1953840 tid:1 priority:10 policy:2t:0x73c3af50 CPU:00 KER_CALL:MSG_RECEIVEV/14 chid:0x00000001 rparts:1t:0x73c3b25e CPU:00 THREAD :THRECEIVE pid:159762 tid:1 priority:10 policy:3...
В этом примере мы собираем два события, которые относятся к двум различным классам. С каждым событием связан обработчик; эти обработчики открывают и закрывают поток. Ниже приведен исходный код программы eh_simple.c
.
Пример иллюстрирует основы использования вызова ядра TraceEvent() и диагностического модуля с утилитой tracelogger в режиме демона. В мониторинге участвуют два события различных классов. Управление мониторингом указанных событий осуществляется с помощью назначенных им обработчиков. Для использования этого примера запустите утилиту tracelogger в режиме демона:
tracelogger -n 1 -d1
После запуска этого примера утилита tracelogger зарегистрирует указанное количество итераций и завершит работу. При успешном завершении примера не печатаются никакие сообщения. Собранные события можно просматривать с помощью утилиты traceprinter.
#include <sys/kercalls.h>#include "common.h"/* Подготовка структуры для хранения данных события и их передачи обработчику */event_data_t e_d_1,e_d_2;_Uint32t data_array_1[20], /* 20 элементов для возможных аргументов */data_array_2[20]; /* 20 элементов для возможных аргументов *//* Глобальная переменная состояния, которая управляет потоком двух событий */int g_state;/* Обработчик события __KER_MSG_SENDV класса _NTO_TRACE_KERCALL */int call_msg_send_eh( event_data_t *e_d ){if ( g_state ){g_state = !g_state;return (1);}return (0);}/* Обработчик события _NTO_TRACE_THRUNNING класса _NTO_TRACE_THREAD (поток) */int thread_run_eh( event_data_t *e_d ){if ( !g_state ){g_state = !g_state;return (1);}return (0);}int main( int argc, char **argv ){/* Заполняем массивы, входящие в состав структур данных событий */e_d_1.data_array = data_array_1;e_d_2.data_array = data_array_2;/* Отключаем все фильтры, поскольку их текущее состояние заранее неизвестно */INIT( argv[0] );/* Установка краткого режима сбора событий */CHECK( argv[0], TraceEvent( _NTO_TRACE_SETALLCLASSESFAST ) );/* Получение привилегий ввода/вывода перед добавлением обработчиков событий */if ( ThreadCtl( _NTO_TCTL_IO, 0 ) != EOK ) /* получение привилегий ввода/вывода */{(void)fprintf( stderr, "argv[0]: Failed to obtain I/O privileges\n" );return (-1);}/* Сбор одного события __KER_MSG_SENDV класса _NTO_TRACE_KERCALL */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_KERCALLENTER, __KER_MSG_SENDV ) );/* Добавление обработчика события __KER_MSG_SENDV класса _NTO_TRACE_KERCALL */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENTHANDLER, _NTO_TRACE_KERCALLENTER,__KER_MSG_SENDV, call_msg_send_eh, &e_d_1 ) );/* Сбор одного события класса _NTO_TRACE_THREAD */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENT, _NTO_TRACE_THREAD, _NTO_TRACE_THRUNNING ) );/* Добавление обработчика события _NTO_TRACE_THRUNNING класса _NTO_TRACE_THREAD (поток) */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDEVENTHANDLER, _NTO_TRACE_THREAD,_NTO_TRACE_THRUNNING, thread_run_eh, &e_d_2 ) );/* Запуск процесса трассировки. В процессе трассировки демон tracelogger регистрирует* все события. Заданное количество итераций равно 1. */CHECK( argv[0], TraceEvent( _NTO_TRACE_START ) );/* Сбор всех событий в течение 1 секунды */(void)sleep( 1 );/* Прекращение трассировки путем закрытия потока событий */CHECK( argv[0], TraceEvent( _NTO_TRACE_STOP ) );/* Сброс внутреннего буфера, поскольку количество сохраненных событий может быть меньше* "высокой отметки" одного буфера (715 событий). Вероятно, в этот момент утилита* tracelogger завершит работу, поскольку количество ее итераций равно 1 (аргумент -n 1). */CHECK( argv[0], TraceEvent( _NTO_TRACE_FLUSHBUFFER ) );/* Удаление обработчиков событий перед завершением во избежание их выполнения в* несуществующем адресном пространстве */CHECK( argv[0], TraceEvent( _NTO_TRACE_DELEVENTHANDLER, _NTO_TRACE_KERCALLENTER, __KER_MSG_SENDV ) );CHECK( argv[0], TraceEvent( _NTO_TRACE_DELEVENTHANDLER, _NTO_TRACE_THREAD, _NTO_TRACE_THRUNNING ) );/* Ожидание длительностью 1 секунду перед завершением для сохранения адресного пространства* обработчиков событий */(void)sleep( 1 );return (0);}
Скомпилируйте программу и запустите утилиту tracelogger:
tracelogger -d1 -n 1 -f eh_simple.kev
![]() | В этом примере мы задали количество итераций равным 1. |
Запустите в другом окне:
./eh_simple
Трассировочные данные находятся в файле eh_simple.kev
. Чтобы изучить его, введите команду:
traceprinter -f eh_simple.kev | less
Результаты утилиты traceprinter выглядят следующим образом:
TRACEPRINTER version 1.02TRACEPARSER LIBRARY version 1.02-- HEADER FILE INFORMATION --TRACE_FILE_NAME:: eh_simple.kevTRACE_DATE:: Wed Jun 24 10:58:41 2009TRACE_VER_MAJOR:: 1TRACE_VER_MINOR:: 01TRACE_LITTLE_ENDIAN:: TRUETRACE_ENCODING:: 16 byte eventsTRACE_BOOT_DATE:: Tue Jun 23 11:47:46 2009TRACE_CYCLES_PER_SEC:: 736629000TRACE_CPU_NUM:: 1TRACE_SYSNAME:: QNXTRACE_NODENAME:: localhostTRACE_SYS_RELEASE:: 6.4.1TRACE_SYS_VERSION:: 2009/05/20-17:35:56EDTTRACE_MACHINE:: x86pcTRACE_SYSPAGE_LEN:: 2264TRACE_TRACELOGGER_ARGS:: tracelogger -d1 -n 1 -f eh_simple.kev-- KERNEL EVENTS --t:0x33139a74 CPU:00 CONTROL: BUFFER sequence = 53, num_events = 482t:0x33139a74 CPU:00 THREAD :THRUNNING pid:1749040 tid:1t:0x362d0710 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00100102)t:0x362d1d04 CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x362e8e3e CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000000 msg:"" (0x00200113)t:0x362ea264 CPU:00 THREAD :THRUNNING pid:4102 tid:8t:0x362f1248 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00000106)t:0x362f1c67 CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x362fd08b CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00100102)t:0x362fd949 CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x36305424 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00000106)t:0x36305e35 CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x3630a572 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00000106)t:0x3630aeb7 CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x3631bd5b CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00100102)t:0x3631c6aa CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x363253bb CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00000106)t:0x36325d95 CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x369b2349 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000003 msg:"" (0x00000106)t:0x369b2bbe CPU:00 THREAD :THRUNNING pid:217117 tid:1t:0x369b88d8 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000007 msg:"" (0x00100106)t:0x369b974a CPU:00 THREAD :THRUNNING pid:1 tid:15t:0x369c48ab CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000008 msg:"" (0x00100106)t:0x369c53db CPU:00 THREAD :THRUNNING pid:126997 tid:2t:0x369cee17 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000008 msg:"" (0x00100106)t:0x369cf533 CPU:00 THREAD :THRUNNING pid:126997 tid:2t:0x369d82b6 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000009 msg:"" (0x00100106)t:0x369d9178 CPU:00 THREAD :THRUNNING pid:8200 tid:10t:0x369eae84 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000006 msg:"" (0x00020100)t:0x369eb687 CPU:00 THREAD :THRUNNING pid:1 tid:15t:0x369f56b1 CPU:00 KER_CALL:MSG_SENDV/11 coid:0x00000006 msg:"" (0x00020100)...
Это важный пример, поскольку в нем демонстрируется решение нетривиальных задач при помощи фильтра с динамическими правилами.
В этом примере демонстрируется вставка пользовательского события в поток событий. Ниже приведен исходный код программы usr_event_simple.c
.
Пример иллюстрирует основы использования вызова ядра TraceEvent() и диагностического модуля с утилитой tracelogger в режиме демона. В мониторинге участвуют все классы и события, которые входят в их состав. Также регистрируются четыре простых события, заданные пользователем, и одно строковое событие. Для использования этого примера запустите утилиту tracelogger в режиме демона:
tracelogger -n количество_итераций -d1
где количество_итераций - число от 1 до 10. После запуска этого примера утилита tracelogger зарегистрирует указанное количество итераций и завершит работу. При успешном завершении примера не печатаются никакие сообщения. Собранные события можно просматривать с помощью утилиты traceprinter. Пользовательские события (класс USREVENT) зарегистрированы с идентификаторами (EVENT) 111, 222, 333, 444 и 555.
#include "common.h"int main(int argc, char **argv){/* Отключаем все фильтры, поскольку их текущее состояние заранее неизвестно */INIT( argv[0] );/* Задаем режим генерации кратких событий всех классов */CHECK( argv[0], TraceEvent( _NTO_TRACE_SETALLCLASSESFAST ) );/* Сбор событий всех классов */CHECK( argv[0], TraceEvent( _NTO_TRACE_ADDALLCLASSES ) );/* Запуск процесса трассировки. В процессе трассировки демон tracelogger регистрирует* все события. При его запуске можно задать количество итераций (т.е. буферов ядра,* в которых регистрируются события). */CHECK( argv[0], TraceEvent( _NTO_TRACE_START ) );/* Вставка четырех простых пользовательских событий и одного строкового события в поток.* Пользовательские события имеют произвольные идентификаторы - 111, 222, 333, 444 и 555* (допустимые значения находятся в диапазоне 0...1023). Пользовательские события с* идентификаторами (111, ..., 444) являются простыми событиями, с которыми связаны два* числа:({1,11}, ..., {4,44}). Строковое пользовательское событие (с идентификатором 555)* содержит строку "Hello world". */CHECK( argv[0], TraceEvent( _NTO_TRACE_INSERTSUSEREVENT, 111, 1, 11 ) );CHECK( argv[0], TraceEvent( _NTO_TRACE_INSERTSUSEREVENT, 222, 2, 22 ) );CHECK( argv[0], TraceEvent( _NTO_TRACE_INSERTSUSEREVENT, 333, 3, 33 ) );CHECK( argv[0], TraceEvent( _NTO_TRACE_INSERTSUSEREVENT, 444, 4, 44 ) );CHECK( argv[0], TraceEvent( _NTO_TRACE_INSERTUSRSTREVENT,555, "Hello world" ) );/* Утилита tracelogger продолжит выполнение до регистрации указанного количества событий */return (0);}
Скомпилируйте программу и запустите утилиту tracelogger:
tracelogger -d1 -n 3 -f usr_event_simple.kev
Запустите в другом окне:
./usr_event_simple
Трассировочные данные находятся в файле usr_event_simple.kev
. Чтобы изучить его, введите команду:
traceprinter -f usr_event_simple.kev | less
Результаты утилиты traceprinter выглядят следующим образом:
TRACEPRINTER version 1.02TRACEPARSER LIBRARY version 1.02-- HEADER FILE INFORMATION --TRACE_FILE_NAME:: usr_event_simple.kevTRACE_DATE:: Wed Jun 24 10:59:34 2009TRACE_VER_MAJOR:: 1TRACE_VER_MINOR:: 01TRACE_LITTLE_ENDIAN:: TRUETRACE_ENCODING:: 16 byte eventsTRACE_BOOT_DATE:: Tue Jun 23 11:47:46 2009TRACE_CYCLES_PER_SEC:: 736629000TRACE_CPU_NUM:: 1TRACE_SYSNAME:: QNXTRACE_NODENAME:: localhostTRACE_SYS_RELEASE:: 6.4.1TRACE_SYS_VERSION:: 2009/05/20-17:35:56EDTTRACE_MACHINE:: x86pcTRACE_SYSPAGE_LEN:: 2264TRACE_TRACELOGGER_ARGS:: tracelogger -d1 -n 3 -f usr_event_simple.kev-- KERNEL EVENTS --t:0x254620e4 CPU:00 CONTROL: BUFFER sequence = 54, num_events = 714...t:0x25496c81 CPU:00 PROCESS :PROCCREATE_NAMEppid:426022pid:1810480name:./usr_event_simplet:0x2549701a CPU:00 THREAD :THCREATE pid:1810480 tid:1t:0x25497112 CPU:00 THREAD :THRUNNING pid:1810480 tid:1t:0x2549793a CPU:00 KER_EXIT:TRACE_EVENT/01 ret_val:0x00000000 empty:0x00000000t:0x25497f48 CPU:00 USREVENT:EVENT:111, d0:0x00000001 d1:0x0000000bt:0x254982c5 CPU:00 USREVENT:EVENT:222, d0:0x00000002 d1:0x00000016t:0x25498638 CPU:00 USREVENT:EVENT:333, d0:0x00000003 d1:0x00000021t:0x25498996 CPU:00 USREVENT:EVENT:444, d0:0x00000004 d1:0x0000002ct:0x25499451 CPU:00 USREVENT:EVENT:555 STR:"Hello world"t:0x2549bde5 CPU:00 KER_CALL:THREAD_DESTROY/47 tid:-1 status_p:0t:0x2549d0d6 CPU:00 KER_EXIT:THREAD_DESTROY/47 ret_val:0x00000030 empty:0x00000000t:0x2549d8ae CPU:00 KER_CALL:THREAD_DESTROYALL/48 empty:0x00000000 empty:0x00000000...
Вставка пользовательских событий позволяет отмечать и группировать события для анализа, а также добавлять нестандартную внутреннюю информацию в поток событий.
Предыдущий раздел: перейти