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

关于内核定时器,及DPC的使用,看来一些代码,这个估计是比较规范的用法了,很基础,希望对新手有帮助
注意,这里的定时器不太精确!
#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值