我有一个minifilter驱动程序的源代码,它记录了文件的不同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
中;完全不同步的并行线程会在10分钟前检查此PWCHAR
,打开-写入-关闭日志并再次分配PWCHAR
(在NonPagedPool中)。
一切正常...但是代码泄漏了内存。几个小时,整个RAM已满。我写了一个测试-它在几秒钟内就充满了RAM。
现在我应该修复它-在需要的地方添加ExFreePoolWithTag
等。
我无法更改架构,即创建用户模式服务并将其用于写入日志。
ExFreePoolWithTag
可能应该在分配之前添加到线程中。
为了同步线程和回调,我们可以使用互斥锁。
但是...让我们去MSDN。它说:POST_OPERATION_CALLBACK
不应获取互斥体。它可以等待他们,但不能获得。
但是MSDN允许使用FltDoCompletionProcessingWhenSafe
和FltQueueDeferredIoWorkItem
。
但是当我的驱动程序要求IRP_MJ_WRITE
使用这些功能时,这些功能将不起作用(它将大量的已写入字节写入日志)。
我们只能使用自旋锁,但是24微秒的限制可能太小。如果CPU速度慢且执行许多任务,我会担心...
结论:我们在这里不能使用任何锁。怎么办?