zoukankan      html  css  js  c++  java
  • Windows驱动开发-DPC定时器

    DCP是一种使用更加灵活的定时器,可以对任意间隔时间进行定时。DPC定时器的内部使用了一个定时器对象KTIMER,当你设定了定时器之后,从设定开始起经过这个时间之后操作系统会将一个DPC定时器的例程插入到DPC的队列,操作系统读取DPC队列的时候定时器例程就能够被执行。这里的DPC定时器例程就相当于一个定时器的回调函数。

    在使用需要一些相关的初始化操作

    1,初始化Timer

    VOID KeInitializeTimer(PKTIMER Timer);
    //参数Timer是定时器的指针

    2,初始化DPC对象

    VOID KeInitializeDpc(PRKDPC Dpc,PKDEFERRED_ROUTINE DeferredRoutine,PVOID DeferredContext);
    //Dpc是输入参数DPC的对象指针
    //DeferredRoutine是一个与DPC关联的定时器例程函数,当定时器被触发的时候这个例程函数就会被执行调用 
    //DeferredContext是一个传入定时器例程的参数

    3,当初始化完成之后使用函数KeSetTimer函数开启定时器,

    BOOLEAN KeSetTimer( PKTIMER Timer,LARGE_INTEGER DueTime,PKDPC Dpc);
    //Timer是定时器对象的指针.
    //DueTimer这个参数是设定的时间间隔.
    //Dpc表示传入定时器例程的参数.
    //返回值:BOOL类型的,表示成功或者失败.

    4,取消定时器使用内核函数KeCancelTimer,

    BOOLEAN KeCancelTimer(PKTIMER Timer);

    在调用KeSetTimer函数之后,经过DueTime的时间,操作系统会调用一次定时器的例程,其中如果DueTime是一个正整数,则会代表绝对时间,也就是相对于1601年1月1日到触发DPC定时器的那个时刻,如果DueTime是负数,那它表示的是间隔多长时间,DueTime的单位是100ns

    示例代码:

    用户层

    #define IO_CONTROL_TRANSMIT_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN,0x8080,METHOD_BUFFERED,FILE_ANY_ACCESS)
    #define IO_CONTROL_START_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8081,METHOD_BUFFERED,FILE_ANY_ACCESS)
    #define IO_CONTROL_STOP_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8082,METHOD_IN_DIRECT,FILE_ANY_ACCESS)
    
    int main()
    {
        HANDLE hDevice = CreateFile(L"\\.\MyDeviceSymbolLinkName01", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hDevice == INVALID_HANDLE_VALUE)
        {
            printf("failed to obtain file handle to device with win32 error code %d ...
    ", GetLastError());
            return 1;
        }
    
        DWORD dwOutput;
        DWORD dwMircoSeconds = 1000 * 1000 * 2;//100ns一个单位
        //发送启动定时器命令
        DeviceIoControl(hDevice, IO_CONTROL_START_TIMER, &dwMircoSeconds, sizeof(DWORD), NULL, 0, &dwOutput, NULL);
    
        Sleep(20000);
        //发送终止定时器命令
        DeviceIoControl(hDevice, IO_CONTROL_STOP_TIMER, NULL, 0, NULL, 0, &dwOutput, NULL);
    
        CloseHandle(hDevice);
        
        return 0;
    }

    驱动层:

    //FirstDriver.h
    #pragma once
    #define IO_CONTROL_TRANSMIT_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN,0x8080,METHOD_BUFFERED,FILE_ANY_ACCESS)
    #define IO_CONTROL_START_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8081,METHOD_BUFFERED,FILE_ANY_ACCESS)
    #define IO_CONTROL_STOP_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8082,METHOD_IN_DIRECT,FILE_ANY_ACCESS)
    typedef struct _DEVICE_EXTENSION
    {
        PDEVICE_OBJECT pDevObj;
        UNICODE_STRING ustrDeviceName;
        UNICODE_STRING ustrSymbolLinkName;
        KDPC pollingDPC;
        KTIMER pollingTimer;
        LARGE_INTEGER pollingInterVal;
    }DEVICE_EXTENSION, * PDEVICE_EXTENSION;
    
    NTSTATUS unload(PDRIVER_OBJECT driver);
    
    NTSTATUS DemoDeviceControlDispatch(PDEVICE_OBJECT pDeviceObject, PIRP pIrp);
    
    NTSTATUS DeviceCreate(PDEVICE_OBJECT pDeviceObject, PIRP pIrp);
    NTSTATUS DeviceClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp);
    
    NTSTATUS DemoCreateDevice(PDRIVER_OBJECT pDriver, PCWSTR devName, PCWSTR devSymName);
    //FirstDriver.c
    #include <ntddk.h>
    #include "FirstDriver.h"
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
    {
        NTSTATUS ntstatus = STATUS_SUCCESS;
        driver->DriverUnload = unload;
        driver->MajorFunction[IRP_MJ_CREATE] = DeviceCreate;//创建
        driver->MajorFunction[IRP_MJ_CLOSE] = DeviceClose;//关闭
        driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DemoDeviceControlDispatch;
    
        ntstatus = DemoCreateDevice(driver, L"\Device\MyDevice01", L"\??\MyDeviceSymbolLinkName01");
        if (!NT_SUCCESS(ntstatus))
        {
            DbgPrint("IoCreateDevice Failed");
            return ntstatus;
        }
    
        DbgPrint("%ws", reg_path->Buffer);
        DbgPrint("driver load success...");
        return STATUS_SUCCESS;
    }
    
    VOID PollingTimerDPC(PKDPC pDpc, PVOID pContext,  PVOID SysArg1, PVOID SysArg2)
    {
        PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pContext;
        PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
        
        KeSetTimer(&pdx->pollingTimer, pdx->pollingInterVal, &pdx->pollingDPC);
        KdPrint(("PollingTimerDpc
    "));
    
        //检验是运行在任意线程上下文
        PEPROCESS pEProcess = IoGetCurrentProcess();
    
        PTSTR ProcessName = (PTSTR)((LONGLONG)pEProcess + 0x174);
    
        DbgPrint("多余参数 %d , %d , %d", pDpc->Number, SysArg1, SysArg2);
        DbgPrint("%s
    ", ProcessName);
    }
    
    NTSTATUS DemoDeviceControlDispatch(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
    {
        NTSTATUS ntstatus = STATUS_SUCCESS;
        DbgPrint("enter DemoDeviceControlDispatch ...
    ");
        
        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
        //ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
        //ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
        ULONG ctlCode = stack->Parameters.DeviceIoControl.IoControlCode;
        PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
    
        ULONG info = 0;
        switch (ctlCode)
        {
        case IO_CONTROL_START_TIMER:
        {
    
            KdPrint(("IOCTL_START_TIMER!
    "));
    
            //从用户模式传进来的超时
            ULONG ulMircoSeconds = *(PULONG)pIrp->AssociatedIrp.SystemBuffer;
    
            pDevExt->pollingInterVal = RtlConvertLongToLargeInteger(ulMircoSeconds * -10);
    
            KeSetTimer(&pDevExt->pollingTimer, pDevExt->pollingInterVal, &pDevExt->pollingDPC);
    
            break;
        }
        case IO_CONTROL_STOP_TIMER:
        {
            KdPrint(("IOCTL_STOP_TIMER!
    "));
    
            KeCancelTimer(&pDevExt->pollingTimer);
    
            break;
        }
        default:
            ntstatus = STATUS_INVALID_VARIANT;
            break;
        }
        pIrp->IoStatus.Status = ntstatus;
        pIrp->IoStatus.Information = info;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        DbgPrint("leave the demo device control dispatch ...");
        DbgPrint("device io control test success...%d", pDeviceObject->ActiveThreadCount);
        return ntstatus;
    }
    
    NTSTATUS DeviceCreate(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
    {
        //业务代码区
    
        //设置返回状态
        pIrp->IoStatus.Status = STATUS_SUCCESS;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        DbgPrint("create device success...%d", pDeviceObject->ActiveThreadCount);
        return STATUS_SUCCESS;
    }
    
    NTSTATUS DeviceClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
    {
        //业务代码区
    
        //设置返回状态
        pIrp->IoStatus.Status = STATUS_SUCCESS;//getLastError()得到的值
        pIrp->IoStatus.Information = 0;            //返回给3环多少数据,没有填0
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        DbgPrint("close device success...%d", pDeviceObject->ActiveThreadCount);
        return STATUS_SUCCESS;
    }
    
    
    NTSTATUS DemoCreateDevice(PDRIVER_OBJECT pDriver, PCWSTR devName, PCWSTR devSymName)
    {
        PDEVICE_OBJECT pDevice;
        PDEVICE_EXTENSION pDevExt;
    
        UNICODE_STRING DeviceName;
        UNICODE_STRING SymbolLinkName;
    
        RtlInitUnicodeString(&DeviceName, devName);
        RtlInitUnicodeString(&SymbolLinkName, devSymName);
    
        NTSTATUS ntstatus = STATUS_SUCCESS;
        ntstatus = IoCreateDevice(pDriver, sizeof(DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevice);
        if (!NT_SUCCESS(ntstatus))
        {
            DbgPrint("IoCreateDevice Failed");
            return ntstatus;
        }
    
        ntstatus = IoCreateSymbolicLink(&SymbolLinkName, &DeviceName);
        if (!NT_SUCCESS(ntstatus))
        {
            DbgPrint("IoCreateSymbolicLink Failed");
            IoDeleteDevice(pDevice);
            return ntstatus;
        }
    
        pDevice->Flags |= DO_BUFFERED_IO;
    
        pDevExt = (PDEVICE_EXTENSION)pDevice->DeviceExtension;
        pDevExt->pDevObj = pDevice;
        pDevExt->ustrDeviceName = DeviceName;
        pDevExt->ustrSymbolLinkName = SymbolLinkName;
    
        KeInitializeTimer(&pDevExt->pollingTimer);
        KeInitializeDpc(&pDevExt->pollingDPC, PollingTimerDPC, (PVOID)pDevice);
        return ntstatus;
    }
    
    
    NTSTATUS unload(PDRIVER_OBJECT driver)
    {
        PDEVICE_OBJECT pDev;
        DbgPrint("driver :%ws unload", driver->DriverName.Buffer);
        pDev = driver->DeviceObject;
        while (pDev != NULL)
        {
            PDEVICE_EXTENSION pDevExt = { 0 };
            pDevExt = (PDEVICE_EXTENSION)pDev->DeviceExtension;
    
            //删除符号链接
            UNICODE_STRING pLinkName = pDevExt->ustrSymbolLinkName;
            DbgPrint("this is the divice name : %ws", pLinkName.Buffer);
            IoDeleteSymbolicLink(&pLinkName);
            pDev = pDev->NextDevice;
            IoDeleteDevice(pDevExt->pDevObj);
        }
        DbgPrint("driver unload success...");
        return STATUS_SUCCESS;
    }
  • 相关阅读:
    mysql修改库、表、字段 字符集,中文排序
    CENTOS6.5 编译安装MySQL5.7.14
    自己的一个小小的目标
    css 浮动和清除浮动
    移动端调试方法
    Fiddler抓包工具总结
    Vue中错误图片的处理
    跨域资源共享 CORS 详解
    十大排序算法JavaScript实现总结
    javascript实现二叉搜索树
  • 原文地址:https://www.cnblogs.com/a-s-m/p/12356432.html
Copyright © 2011-2022 走看看