最近调试驱动程序,以前写服务程序经常写一些Log的,在驱动中为了实现Log,着实让我头大了一回,不知道各位有什么经验可以分享。
设计了几个LogFile的操作函数,普通的驱动代码使用上没有什么问题,但是当驱动中使用了KeAttachProcess这样的进程上下文切换之后驱动会经常的兰屏,调试了几天才发现Log的影响,目前只能在使用KeAttachProcess前禁止Log,调用KeDetachProcess之后再次打开Log。
Log的写操作代码如下:
#define MAX_STRBUF_LENGTH 1024BOOLEAN _cdecl WriteLine(HANDLE hLogFile, LPSTR lpszLine, ...){ if(!g_bLogValid) return TRUE; va_list pParam; va_start(pParam, lpszLine);
LPSTR lpszOutput = (LPSTR)ExAllocatePoolWithTag(NonPagedPool, MAX_STRBUF_LENGTH, 'FZM0'); if(lpszOutput != NULL) { LARGE_INTEGER curTime; LARGE_INTEGER localTime; TIME_FIELDS timeNow;
KeQuerySystemTime(&curTime); ExSystemTimeToLocalTime(&curTime, &localTime); RtlTimeToTimeFields(&localTime, &timeNow);
RtlZeroMemory(lpszOutput, MAX_STRBUF_LENGTH); RtlStringCbPrintfA(lpszOutput, MAX_STRBUF_LENGTH, "%04d-%02d-%02d %02d::%02d::%02d %04d ", timeNow.Year, timeNow.Month, timeNow.Day, timeNow.Hour, timeNow.Minute, timeNow.Second, timeNow.Milliseconds);
ULONG nLen; RtlStringCchLengthA(lpszOutput, MAX_STRBUF_LENGTH, (size_t*)&nLen);
RtlStringCbVPrintfA(lpszOutput+nLen, MAX_STRBUF_LENGTH-nLen, lpszLine, pParam); DbgPrint(lpszOutput);
RtlStringCchLengthA(lpszOutput, MAX_STRBUF_LENGTH, (size_t*)&nLen); IO_STATUS_BLOCK ioStatusBlock; if(hLogFile != NULL) { ZwWriteFile(hLogFile, NULL, NULL, NULL, &ioStatusBlock, (PVOID)lpszOutput, nLen, NULL, NULL); }
ExFreePoolWithTag(lpszOutput, 'FZM0'); return TRUE; } return FALSE;}
对于KeAttachProcess上下文切换影响什么不是很确定,贴出来抛砖引玉!
很多驱动程序(包括微软自己的)使用ETW(Event Trace for Windows)来代替Log机制辅助调试,可以将信息以二进制形式输出给系统中的ETW消耗器。这种方法比上面说的两种Log都强大。但是因为它与传统意义的log有所不同,所以《软件调试》没有将其放入Log中讨论,前面回帖时也没有提。
顺便欢迎MJ0011光临本站。