Курсовая работа: Профилировщик приложений
Замечание : память под объекты ядра должна выделяться исключительно в нестраничном пуле (ключевое слово NonPagedPool).
Таймеры могут быть двух типов:
SynchronizationTimer — по истечении указанного временного интервала или очередного периода, он переводится в сигнальное состояние, пока один из потоков, ждущих его, не будет пробуждён. Тогда же таймер переводится в несигнальное состояние.
NotificationTimer — по истечении указанного временного интервала или очередного периода, он переводится в сигнальное состояние, причём пробуждаются все потоки ожидающие на нём. Такой таймер остаётся в сигнальном состоянии до тех пор, пока он не будет явно переведён в несигнальное.
Для того, чтобы выполнять какую-то полезную работу по таймеру, необходимо зарегистрировать DPC-процедуру OnTimer(). Для неё необходимо создать собственный DPC-объект, который будет периодически ставится в общесистемную очередь:
status = _ExAllocatePool( g_pTimerDpc, NonPagedPool, sizeof( KDPC ) );
KeInitializeDpc( g_pTimerDpc, OnTime, NULL );
Далее, в силу того, что в данном драйвере по таймеру должны выполняться действия, требующие пользовательского контекста, необходимо их вынести из функции OnTimer(), которая является DPC-процедурой, а следовательно, во время её выполнения доступен лишь системный контекст. Тем не менее, необходимо обеспечить приемлемую синхронность выполнения необходимой работы с моментом извлечения DPC-объекта функции из очереди для обработки. Для этого создадим поток, который будет посвящён ожиданию некоторого события:
OBJECT_ATTRIBUTES objectAttributes;
InitializeObjectAttributes( &objectAttributes, NULL, OBJ_KERNEL_HANDLE,
NULL, NULL );
status = PsCreateSystemThread( &hThread, THREAD_ALL_ACCESS, &objectAttributes,
NULL, NULL, UpdateThreadFunc, NULL );
KeInitializeEvent( g_pUpdateEvent, SynchronizationEvent, FALSE );
Замечание : объекты ядра «события» по своему типу идентичны объектам ядра «таймер».
При поступлении этого события поток будет обновлять системную информацию о процессах и их потоках. Объект этого события будем переводить в сигнальное состояние в функции OnTimer(). Данный способ синхронизации позволил обеспечить выполнение необходимых действий через заданный интервалом с точностью до милисекунды, что следует из нижеприведённых сообщений, перехваченных программой DebugView от отладочной версии драйвера:
0.00075233 [Spectator] ^^^^^^^^ OnTime ^^^^^^^^
0.00116579 [Spectator] ======== LockInfo ========
0.00118814 [Spectator] ======== ReloadInfo ========
0.99727142 [Spectator] ^^^^^^^^ OnTime ^^^^^^^^
1.00966775 [Spectator] ======== LockInfo ========
1.00968981 [Spectator] ======== ReloadInfo ========
1.99729049 [Spectator] ^^^^^^^^ OnTime ^^^^^^^^
2.05610037 [Spectator] ======== LockInfo ========
2.05632067 [Spectator] ======== ReloadInfo ========
2.99727035 [Spectator] ^^^^^^^^ OnTime ^^^^^^^^
2.99741030 [Spectator] ======== LockInfo ========
2.99743295 [Spectator] ======== ReloadInfo ========
3.99727631 [Spectator] ^^^^^^^^ OnTime ^^^^^^^^