У меня есть исходный код драйвера минифильтра, который регистрирует различные IRP-операции с файлами.
Архитектура драйвера довольно проста в своей простоте ...
Он имеет PRE_OPERATION_CALLBACK
, этот обратный вызовпусто.
Имеет POST_OPERATION_CALLBACK
.Этот обратный вызов получает данные от операций и другими способами (например, получение PID операции, выданной процессом) и добавляет эти данные в журнал «очереди».
И отдельный поток запускается следующим образом:
PsCreateSystemThread(hThread, (ACCESS_MASK)0,
NULL,
(HANDLE) 0,
NULL,
loggerThread,
NULL);
Тема каждые 10 минут проверяет, не заполнена ли очередь.И он заполнен, поток записывает его в журнал (журнал - это файл, но поток также выполняет некоторую обработку данных перед записью - т.е. архивирование и шифрование) и очищает «очередь».
Что такое «очередь»«?Это просто PWCHAR
объявлено глобально.Это даже не UNICODE_STRING
.Это:
PWCHAR szLogQueue;
Подводя итог: обратный вызов добавляет данные в глобальный PWCHAR
;полностью несинхронизированные параллельные потоки проверяют это PWCHAR
в первые 10 минут, открывает-пишет-закрывает журнал и снова выделяет PWCHAR
(в NonPagedPool).
И все работает ... но код утечки памяти.Несколько часов и вся оперативная память заполнена.Я написал тест - и он за несколько секунд заполняет оперативную память.
Теперь я должен исправить это - добавить ExFreePoolWithTag
, где это необходимо и т. Д.
Я не смог изменить архитектуру, т.е. создать пользовательский режимservice и использовать его для записи журнала.
ExFreePoolWithTag
, вероятно, следует добавить в поток перед выделением.
Для синхронизации потока и обратного вызова мы могли бы использовать мьютексы.
Но... Пойдем в MSDN.Он говорит: POST_OPERATION_CALLBACK
не должен приобретать мьютексы.Он может ждать их, но не получать.
Но MSDN позволяет использовать FltDoCompletionProcessingWhenSafe
и FltQueueDeferredIoWorkItem
.
Но эти функции не работают с IRP_MJ_WRITE
, когда мой драйвер требует его работы (онзаписывает количество записанных байтов в журнал).
Единственный тип блокировки, который мы могли бы использовать, это спин-блокировки , но ограничение в 24 микросекунды может быть слишком маленьким.Я делаю это, если процессор медленный и много задач ...
Вывод: мы не могли использовать здесь какие-либо блокировки.А что делать?