標籤:bre kernel out adp 建立線程 模式 content etc get
完整的程式在下載:http://download.csdn.net/detail/dijkstar/7913249
使用者層建立的事件Event是一個Handle控制代碼,和核心中的建立的核心模式下的KEVENT是一個東西。因此,在應用程式層建立的事件,可以在核心層獲得並使用。這一部分的原理,見張帆編著的《Windows驅動技術詳解》章節8.5.4,P237頁;
程式是來自於《Windows驅動技術詳解》章節8.5.4(驅動程式和應用程式互動事件對象)和章節10.2.1(DPC定時器)。
首先,在應用程式層建立一個等待事件Event,建立監控這個等待事件的線程,並把等待事件Event傳遞給核心:
- //
- //1. 建立使用者層的等待事件,傳入核心
- //2. 建立線程,用於監測核心事件的到來
- //
- HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, Thread1, &hEvent, 0, NULL);
-
- //先將使用者層的等待Event傳入核心
- DeviceIoControl(hDevice, IOCTL_SET_EVENT, &hEvent, sizeof(hEvent), NULL, 0, &dwOutput, NULL);
監控線程的內容:(裡面用了查詢指令周期數,可以測試每次等待WaitFor××的時間)
- UINT WINAPI Thread1(LPVOID para)
- {
- HANDLE *phEvent = (HANDLE *)para;
- while(1)
- {
- //獲得初始值
- QueryPerformanceCounter(&litmp);
- qt1=litmp.QuadPart;
-
- //等待
- WaitForSingleObject(*phEvent, INFINITE);
-
-
- //獲得終止值
- QueryPerformanceCounter(&litmp);
- qt2=litmp.QuadPart;
- //獲得對應的時間值,轉到毫秒單位上
- dfm=(double)(qt2-qt1);
- dft=dfm/dff;
-
-
- printf("本次等待用時: %.3f 毫秒\n", dft*1000.0);
- }
- }
使用者層還通知驅動核心啟動一個DPC定時器,用於每次來觸發應用程式層的等待事件Event:
- DWORD dwMircoSeconds = 1000 * 50;//單位微秒
- DeviceIoControl(hDevice, IOCTL_START_TIMER, &dwMircoSeconds, sizeof(DWORD), NULL, 0, &dwOutput, NULL);
在驅動程式中,首先取出來應用程式層傳遞進來的事件,並把它轉化為核心對象:
- case IOCTL_SET_EVENT:
- {
- //把傳遞進來的使用者層等待事件取出來
- HANDLE hUserEvent = *(HANDLE *)pIrp->AssociatedIrp.SystemBuffer;
-
- //將使用者層事件轉化為核心等待對象
- status = ObReferenceObjectByHandle(hUserEvent, EVENT_MODIFY_STATE,
- *ExEventObjectType, KernelMode, (PVOID*)&pDevExt->pEvent, NULL);
-
- KdPrint(("status = %d\n", status));//status應該為0才對
-
- ObDereferenceObject(pDevExt->pEvent);
- break;
- }
在核心的每次定時器到來時,啟用等待事件,等於觸發啟用應用程式層的WaitFor××函數向下繼續執行:
- #pragma LOCKEDCODE
- VOID PollingTimerDpc( IN PKDPC pDpc,
- IN PVOID pContext,
- IN PVOID SysArg1,
- IN PVOID SysArg2 )
- {
- PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pContext;
- PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
- KeSetTimer(
- &pdx->pollingTimer,
- pdx->pollingInterval,
- &pdx->pollingDPC );
- KdPrint(("PollingTimerDpc\n"));
-
- //定時器到來,通知使用者層
- if(pdx->pEvent)
- KeSetEvent(pdx->pEvent, IO_NO_INCREMENT, FALSE);
-
-
- /*
- //檢驗是運行在任意線程上下文
- PEPROCESS pEProcess = IoGetCurrentProcess();
- PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);
- KdPrint(("%s\n",ProcessName));
- */
- }
程式中其他部分見源碼解釋,這個程式還有兩個問題,一是應用程式層必須正常退出,否則驅動核心層因不能正常關閉DPC定時器,而繼續執行已經找不到的等待事件,引起藍屏崩潰;二是雖然在核心裡,DPC定時器的觸發精度為1個100ns層級,但當觸發周期設定為20ms以下時,在應用程式層監控WaitFor,都是十幾個毫秒的分辨精度,再向下設定已經沒有意義。
jpg 改 rar
向Windows核心驅動傳遞使用者層定義的事件Event,並響應核心層的通知