驱动程序开发技术详解读书笔记(四)

/************************************************************************
* 文件名称:HelloWDM.cpp                                                
* 作    者:张帆
* 完成日期:2007-11-1
*************************************************************************/
#include "HelloWDM.h"

/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
      pDriverObject:从I/O管理器中传进来的驱动对象
      pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
#pragma INITCODE //将driverEntry设在分页内存中,当驱动加载成功,此函数在内存中移除。
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
                                IN PUNICODE_STRING pRegistryPath)
{
    KdPrint(("Enter DriverEntry/n"));
//下面是设置回调函数
    pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
    pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
    pDriverObject->MajorFunction[IRP_MJ_CREATE] =
    pDriverObject->MajorFunction[IRP_MJ_READ] =
    pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
    pDriverObject->DriverUnload = HelloWDMUnload;

    KdPrint(("Leave DriverEntry/n"));
 //下面返回驱动加载状态。

    return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:HelloWDMAddDevice
* 功能描述:添加新设备
* 参数列表:
      DriverObject:从I/O管理器中传进来的驱动对象
      PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象
* 返回 值:返回添加新设备状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
                           IN PDEVICE_OBJECT PhysicalDeviceObject)
{
    PAGED_CODE();//当例程所在的中断请求级超过APC_LEVEL时,会产生一个断言,断言会使程序终止。
    KdPrint(("Enter HelloWDMAddDevice/n"));

    NTSTATUS status;  //设定状态 变量
    PDEVICE_OBJECT fdo; //定义设备对象 变量
    UNICODE_STRING devName; //定义设备名称字符串变量
    RtlInitUnicodeString(&devName,L"//Device//MyWDMDevice");/ / 指定devName="//Device//MyWDMDevice"

//下面是创建设备对象,并返回创建是否成功。
        status = IoCreateDevice(
        DriverObject,   //驱动对象
        sizeof(DEVICE_EXTENSION), //驱动扩展部分的空间大小
        &(UNICODE_STRING)devName, //设备名称
        FILE_DEVICE_UNKNOWN, //设备类型
        0, //为设备对象提供Characteristics 标志
        FALSE, //设备之间是互斥的
        &fdo);//创建的设备对象
    if( !NT_SUCCESS(status))
        return status;   //如果创建设备对象失败,则返回失败原因,并结束程序。
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension; //得到设备对象扩展结构首地址
    pdx->fdo = fdo; //指明设备扩展中的功能设备是刚刚创建的设备对象,我的理解就是这个设备扩展属于刚刚创建的那个设备fdo。
    pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
    UNICODE_STRING symLinkName;//将fdo挂在设备堆栈上,什么是设备堆栈,我现在还不清楚,后面再看吧
    RtlInitUnicodeString(&symLinkName,L"//DosDevices//HelloWDM");//创建设备的符号链接

    pdx->ustrDeviceName = devName;
    pdx->ustrSymLinkName = symLinkName;
    status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);

 

//如果创建符号链接失败,则删除刚刚创建的符号,并重新创建一次,如果两次都未成功,则返回失败状态,并退出程序。
    if( !NT_SUCCESS(status))
    {
        IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
        status = IoCreateSymbolicLink(&symLinkName,&devName);
        if( !NT_SUCCESS(status))
        {
            return status;
        }
    }
//下面两行设定设备为BUFFERED_IO设备,并指明驱动初始化完成。
    fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
    fdo->Flags &= ~DO_DEVICE_INITIALIZING;

    KdPrint(("Leave HelloWDMAddDevice/n"));
    return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:DefaultPnpHandler
* 功能描述:对PNP IRP进行缺省处理
* 参数列表:
      pdx:设备对象的扩展
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
{
    PAGED_CODE();
    KdPrint(("Enter DefaultPnpHandler/n"));
    IoSkipCurrentIrpStackLocation(Irp);//略过当前堆栈
    KdPrint(("Leave DefaultPnpHandler/n"));
    return IoCallDriver(pdx->NextStackDevice, Irp);//用下层堆栈的驱动设备对象处理此IRP。
}

/************************************************************************
* 函数名称:HandleRemoveDevice
* 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理
* 参数列表:
      fdo:功能设备对象
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
    PAGED_CODE();
    KdPrint(("Enter HandleRemoveDevice/n"));

    Irp->IoStatus.Status = STATUS_SUCCESS;//设定IRP的状态为顺利完成
    NTSTATUS status = DefaultPnpHandler(pdx, Irp);//调用默认的PNP的IRP的处理函数,默认的就是前面刚看到的那个函数DefaultPnpHandler
    IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);//删除此设备的符号链接

    //调用IoDetachDevice()把fdo从设备栈中脱开:
    if (pdx->NextStackDevice)
        IoDetachDevice(pdx->NextStackDevice);
   
    //删除fdo:
    IoDeleteDevice(pdx->fdo);
    KdPrint(("Leave HandleRemoveDevice/n"));
    return status;
}

/************************************************************************
* 函数名称:HelloWDMPnp
* 功能描述:对即插即用IRP进行处理
* 参数列表:
      fdo:功能设备对象
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
                        IN PIRP Irp)
{
    PAGED_CODE();

    KdPrint(("Enter HelloWDMPnp/n"));
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); //不懂啊
    static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =
    {
        DefaultPnpHandler,        // IRP_MN_START_DEVICE
        DefaultPnpHandler,        // IRP_MN_QUERY_REMOVE_DEVICE
        HandleRemoveDevice,        // IRP_MN_REMOVE_DEVICE
        DefaultPnpHandler,        // IRP_MN_CANCEL_REMOVE_DEVICE
        DefaultPnpHandler,        // IRP_MN_STOP_DEVICE
        DefaultPnpHandler,        // IRP_MN_QUERY_STOP_DEVICE
        DefaultPnpHandler,        // IRP_MN_CANCEL_STOP_DEVICE
        DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_RELATIONS
        DefaultPnpHandler,        // IRP_MN_QUERY_INTERFACE
        DefaultPnpHandler,        // IRP_MN_QUERY_CAPABILITIES
        DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCES
        DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
        DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_TEXT
        DefaultPnpHandler,        // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
        DefaultPnpHandler,        //
        DefaultPnpHandler,        // IRP_MN_READ_CONFIG
        DefaultPnpHandler,        // IRP_MN_WRITE_CONFIG
        DefaultPnpHandler,        // IRP_MN_EJECT
        DefaultPnpHandler,        // IRP_MN_SET_LOCK
        DefaultPnpHandler,        // IRP_MN_QUERY_ID
        DefaultPnpHandler,        // IRP_MN_QUERY_PNP_DEVICE_STATE
        DefaultPnpHandler,        // IRP_MN_QUERY_BUS_INFORMATION
        DefaultPnpHandler,        // IRP_MN_DEVICE_USAGE_NOTIFICATION
        DefaultPnpHandler,        // IRP_MN_SURPRISE_REMOVAL
    };

    ULONG fcn = stack->MinorFunction;
    if (fcn >= arraysize(fcntab))
    {                        // unknown function
        status = DefaultPnpHandler(pdx, Irp); // some function we don't know about
        return status;
    }                        // unknown function

 

//下面是打印调试信息用的
#if DBG
    static char* fcnname[] =
    {
        "IRP_MN_START_DEVICE",
        "IRP_MN_QUERY_REMOVE_DEVICE",
        "IRP_MN_REMOVE_DEVICE",
        "IRP_MN_CANCEL_REMOVE_DEVICE",
        "IRP_MN_STOP_DEVICE",
        "IRP_MN_QUERY_STOP_DEVICE",
        "IRP_MN_CANCEL_STOP_DEVICE",
        "IRP_MN_QUERY_DEVICE_RELATIONS",
        "IRP_MN_QUERY_INTERFACE",
        "IRP_MN_QUERY_CAPABILITIES",
        "IRP_MN_QUERY_RESOURCES",
        "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
        "IRP_MN_QUERY_DEVICE_TEXT",
        "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
        "",
        "IRP_MN_READ_CONFIG",
        "IRP_MN_WRITE_CONFIG",
        "IRP_MN_EJECT",
        "IRP_MN_SET_LOCK",
        "IRP_MN_QUERY_ID",
        "IRP_MN_QUERY_PNP_DEVICE_STATE",
        "IRP_MN_QUERY_BUS_INFORMATION",
        "IRP_MN_DEVICE_USAGE_NOTIFICATION",
        "IRP_MN_SURPRISE_REMOVAL",
    };

    KdPrint(("PNP Request (%s)/n", fcnname[fcn]));
#endif // DBG

    status = (*fcntab[fcn])(pdx, Irp);
    KdPrint(("Leave HelloWDMPnp/n"));
    return status;
}

/************************************************************************
* 函数名称:HelloWDMDispatchRoutine
* 功能描述:对缺省IRP进行处理
* 参数列表:
      fdo:功能设备对象
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
                                 IN PIRP Irp)
{
    PAGED_CODE();
    KdPrint(("Enter HelloWDMDispatchRoutine/n"));
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;    // no bytes xfered
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    KdPrint(("Leave HelloWDMDispatchRoutine/n"));
    return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:HelloWDMUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:
      DriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
{
    PAGED_CODE();
    KdPrint(("Enter HelloWDMUnload/n"));
    KdPrint(("Leave HelloWDMUnload/n"));
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
《Linux设备驱动程序开发详解第2版》是一本针对Linux系统下设备驱动程序开发的重要参考书籍。下面给出对该书的详细回答。 《Linux设备驱动程序开发详解第2版》这本书的作者是Robert Love,它是一本权威的Linux设备驱动程序开发指南。该书首先介绍了设备驱动程序的基本概念和原理,包括设备文件、设备号、设备结构体等。然后,它详细讲解了Linux内核提供的设备驱动框架,包括字符设备驱动、块设备驱动和网络设备驱动。书中介绍了开发设备驱动程序的各种基本技术和工具,如模块管理、内存管理和中断处理等。 该书还通过大量的示例代码和实践案例,帮助读者深入理解设备驱动程序开发过程。例如,它详细描述了如何编写一个字符设备驱动程序,并介绍了如何使用ioctl系统调用和proc文件系统来与设备进行通信。此外,书中还介绍了如何使用Linux内核提供的调试工具来调试设备驱动程序,以及如何编写可移植的驱动程序。 《Linux设备驱动程序开发详解第2版》在第一版的基础上进行了更新和扩充。它新增了对新版本Linux内核的支持,并添加了更多实例和案例。此外,该书还介绍了设备模型和总线驱动程序的概念,让读者了解如何开发可移植的设备驱动程序。 总之,《Linux设备驱动程序开发详解第2版》是一本非常有价值的书籍,对于想要深入了解和掌握Linux设备驱动程序开发的人来说,是一本必读的参考书。它全面而详细地介绍了设备驱动程序开发原理、技术和工具,通过丰富的实例和案例,帮助读者更好地理解和掌握设备驱动程序开发的要点。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值