您的位置:首页 > 其它

关于内核定时器,DPC,线程的使用

2016-06-19 22:17 423 查看
[cpp] view
plain copy

关于内核定时器,及DPC的使用,看来一些代码,这个估计是比较规范的用法了,很基础,希望对新手有帮助  

注意,这里的定时器不太精确!  

[cpp] view
plain copy

#include <ntddk.h>  

typedef struct _DEVICE_EXTENSION {  

      

    LIST_ENTRY      list_head;  

    KSPIN_LOCK      list_lock;      

    PVOID           thread_pointer;  

    BOOLEAN            terminate_thread;      

    KEVENT          request_event;  

    KTIMER            my_timer;  

    KDPC            KiTimerExpireDpc;      

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;  

#define dprintf if (DBG) DbgPrint  

#define nprintf DbgPrint  

#define DEVICE_NAME L"\\Device\\devhello" // Driver Name  

#define LINK_NAME L"\\DosDevices\\hello"  // Link Name  

//  

// The device driver IOCTLs  

//  

#define IOCTL_BASE    0x800  

#define MY_CTL_CODE(i) \  

CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)  

#define IOCTL_HELLO    MY_CTL_CODE(0)  

/////////////////////////////////////////////////////////////////////  

//函数声明  

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString);  

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);  

NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);  

VOID     DriverUnload(PDRIVER_OBJECT pDriverObj);  

NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);  

VOID  

KiTimerExpirationFunction (  

                           IN struct _KDPC  *Dpc,  

                           IN PVOID  DeferredContext,  

                           IN PVOID  SystemArgument1,  

                           IN PVOID  SystemArgument2  

                           );  

NTSTATUS ThreadFunc ( IN PVOID Context);  

/////////////////////////////////////////////////////////////////////  

  

NTSTATUS   

DriverEntry(  

    PDRIVER_OBJECT pDriverObj,   

    PUNICODE_STRING pRegistryString  

    )  

{  

    NTSTATUS status = STATUS_SUCCESS;  

    UNICODE_STRING ustrLinkName;  

    UNICODE_STRING ustrDevName;      

    PDEVICE_OBJECT device_object;  

    PDEVICE_EXTENSION device_extension;  

    HANDLE  thread_handle;  

/* 

    在驱动中是以100纳秒为单位的 

    1000纳秒=1微秒 

    1000微秒=1毫秒 

    1000毫秒=1秒    10*1000*1000 

*/  

    LARGE_INTEGER duetime = {0};  

    #define POLLING_INTERVAL 3000  

    dprintf("[hello] DriverEntry\n");  

      

    pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;  

    pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;  

    pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;  

    pDriverObj->DriverUnload = DriverUnload;  

  

    RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);  

    status = IoCreateDevice(pDriverObj,   

                sizeof(DEVICE_EXTENSION),  

                &ustrDevName,   

                FILE_DEVICE_UNKNOWN,  

                0,  

                FALSE,  

                &device_object);  

    if(!NT_SUCCESS(status))    {  

        dprintf("[hello] IoCreateDevice = 0x%x\n", status);  

        return status;  

    }  

    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);  

    status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);   

      

    if(!NT_SUCCESS(status)) {  

        dprintf("[hello] IoCreateSymbolicLink = 0x%x\n", status);  

        IoDeleteDevice(device_object);    

        return status;  

    }  

    device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;  

    InitializeListHead(&device_extension->list_head);      

    KeInitializeSpinLock(&device_extension->list_lock);  

      

    KeInitializeEvent(    &device_extension->request_event,  

        NotificationEvent,  

                         FALSE);  

//    KeInitializeTimer(&my_timer);//这是个旧的函数  

    KeInitializeTimerEx(&device_extension->my_timer, NotificationTimer);  

    // 初始化定时器过期的DPC对象    

    KeInitializeDpc(&device_extension->KiTimerExpireDpc,  

    (PKDEFERRED_ROUTINE)KiTimerExpirationFunction, (PVOID) device_object);  

//    KeSetTimer(&my_timer,timeout,&KiTimerExpireDpc); 仅仅只能设置一次  

//    KeSetTimerEx(&my_timer, timeout, period, &KiTimerExpireDpc);这个可以循环设置  

    KeSetTimerEx(&device_extension->my_timer, duetime, POLLING_INTERVAL, &device_extension->KiTimerExpireDpc);    

//    KeSetTimerEx语句启动周期定时器。由于duetime参数是0,  

//    所以定时器立即进入信号态。  

//  然后每隔POLLING_INTERVAL=3秒触发一次。  

    device_extension->terminate_thread = FALSE;  

      

    status = PsCreateSystemThread(  

        &thread_handle,  

        (ACCESS_MASK) 0L,  

        NULL,  

        NULL,  

        NULL,  

        ThreadFunc,  

        device_object  

        );  

    if (!NT_SUCCESS(status))  

    {  

        IoDeleteDevice(device_object);  

        return status;  

    }  

      

    status = ObReferenceObjectByHandle(  

        thread_handle,  

        THREAD_ALL_ACCESS,  

        NULL,  

        KernelMode,  

        &device_extension->thread_pointer,  

        NULL  

        );  

      

    if (!NT_SUCCESS(status))  

    {  

        ZwClose(thread_handle);  

        device_extension->terminate_thread = TRUE;//如果出错就关闭创建的线程  

          

        KeSetEvent(  

            &device_extension->request_event,  

            (KPRIORITY) 0,  

            FALSE  

            );  

        IoDeleteDevice(device_object);      

        return status;  

    }  

      

    ZwClose(thread_handle);  

    return STATUS_SUCCESS;  

}  

VOID  

KiTimerExpirationFunction (  

           IN struct _KDPC  *Dpc,  

           IN PVOID  DeferredContext,  

           IN PVOID  SystemArgument1,  

           IN PVOID  SystemArgument2  

           )  

{      

PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)DeferredContext;  

PDEVICE_EXTENSION device_extension = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;  

//kesetevent 必需在较低级别用  

//ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);  

//dprintf("level in timer function  is %x\n",KeGetCurrentIrql());  

dprintf("haha dpc function work\n");  

KeSetEvent(&device_extension->request_event,  

            (KPRIORITY) 0,  

            FALSE);  

};  

NTSTATUS ThreadFunc ( IN PVOID Context)  

{   

    PFILE_OBJECT ConnectionFileObject, AddressFileObject;   

    HANDLE AddressHandle, ConnectionHandle;   

    NTSTATUS Status;   

    IO_STATUS_BLOCK IoStatus;  

    KEVENT Event;  

    PDEVICE_OBJECT      device_object;  

    PDEVICE_EXTENSION   device_extension;  

    device_object = (PDEVICE_OBJECT) Context;  

    device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;  

      

    KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);  

//****************************  

//****************************  

//开始工作   此处用2重循环,你可以添加实际的代码  

for (;;)  

{      

    do   

    {  

       dprintf("thread work ok !!\n");  

       goto failselabel;  

      } while (TRUE);  

failselabel:  

   KeWaitForSingleObject(  

       &device_extension->request_event,  

       Executive,  

       KernelMode,  

       FALSE,  

       NULL  

       );//在这儿等  

    //KeClearEvent(&Event);//清除一下试试  

           //killvxk 2007-01-31 11:18   

    //严重提醒不要使用KeClearEvent(&Event);   

    //如果你还要用那个事件就不要用那个Clear,要其它手段~如果你不需要那个event了,  

           //那你应该在thread里判断下~   

   KeResetEvent(&device_extension->request_event);  

   if (  device_extension->terminate_thread )  

    {  

      PsTerminateSystemThread(STATUS_SUCCESS);  

    }  

}  

dprintf("never be here !\n");  

    return Status;   

}  

  

VOID   

DriverUnload(  

    PDRIVER_OBJECT pDriverObj  

    )  

{      

    PDEVICE_EXTENSION   device_extension;  

    UNICODE_STRING strLink;  

    RtlInitUnicodeString(&strLink, LINK_NAME);  

    device_extension = (PDEVICE_EXTENSION) pDriverObj->DeviceObject->DeviceExtension;  

//停止创建的线程  

    if (KeCancelTimer(&device_extension->my_timer) == FALSE)  

    {  

        //    KeCancelTimer(&device_extension->my_timer);//取消定时器  

        dprintf( " no timer active at terminate\n");  

    }  

    device_extension->terminate_thread = TRUE;//停止线程  

    KeSetEvent(  

        &device_extension->request_event,  

        (KPRIORITY) 0,  

        FALSE  

        );  

    KeWaitForSingleObject(  

        device_extension->thread_pointer,//等待线程对象结束,注意哦,是对象  

        Executive,  

        KernelMode,  

        FALSE,  

        NULL  

        );  

    ObDereferenceObject(device_extension->thread_pointer);  

    IoDeleteSymbolicLink(&strLink);  

    IoDeleteDevice(pDriverObj->DeviceObject);  

    dprintf("[hello] Unloaded\n");  

}  

  

NTSTATUS   

DispatchCreate(  

    PDEVICE_OBJECT pDevObj,   

    PIRP pIrp  

    )  

{  

    pIrp->IoStatus.Status = STATUS_SUCCESS;  

    pIrp->IoStatus.Information = 0;  

    dprintf("[hello] IRP_MJ_CREATE\n");  

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);  

    return STATUS_SUCCESS;  

}  

  

NTSTATUS   

DispatchClose(  

    PDEVICE_OBJECT pDevObj,   

    PIRP pIrp  

    )  

{  

    pIrp->IoStatus.Status = STATUS_SUCCESS;  

    pIrp->IoStatus.Information = 0;  

    dprintf("[hello] IRP_MJ_CLOSE\n");  

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);  

    return STATUS_SUCCESS;  

}  

  

NTSTATUS   

DispatchIoctl(  

    PDEVICE_OBJECT pDevObj,   

    PIRP pIrp  

    )  

{  

    NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;  

    PIO_STACK_LOCATION pIrpStack;  

    ULONG uIoControlCode;  

    PVOID pIoBuffer;  

    ULONG uInSize;  

    ULONG uOutSize;  

    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);  

    uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;  

    pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;  

    uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;  

    uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;  

    switch(uIoControlCode) {  

        case IOCTL_HELLO: {  

              

            dprintf("[hello] Hello\n");  

            status = STATUS_SUCCESS;  

        }  

        break;  

    }  

    if(status == STATUS_SUCCESS)  

        pIrp->IoStatus.Information = uOutSize;  

    else  

        pIrp->IoStatus.Information = 0;  

      

    /////////////////////////////////////  

    pIrp->IoStatus.Status = status;  

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);  

    return status;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: