驱动入口函数
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
这个驱动程序包含了三个函数:DriverEntry、HelloDDKUnload和HelloDDKDispatchRoutine。其中DriverEntry是驱动程序的入口函数,相当于C/C++程序的main函数,HelloDDKUnload函数是驱动卸载函数。而HelloDDKDispatchRuntine则是IRP的派遣函数,因为驱动程序主要是处理IO 请求,而IO请求大多是在派遣函数中处理的。
先来看看这个驱动程序的第一个函数:DriverEntry
/****************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
pDriverObject:从I/O管理器中传来的驱动对象
pRegistryPath:驱动程序在注册表中的路径
* 返回值:返回初始化驱动状态
****************************************************************/
#pragma INITCODE
extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath )
{
NTSTATUS status;
KdPrint( ( "Enter DriverEntry!\n" ) );
//注册其它驱动调用函数入口
pDriverObject->DriverUnload = ( PDRIVER_UNLOAD ) HelloDDKUnload; pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
//创建驱动设备对象
status = CreateDeivce( pDriverObject );
KdPrint( ( "DriverEntry end!\n" ) );
return status;
}
这个函数的第一句代码是一个#pragma预处理指令:
#pragma INITCODE
这段代码表明将此函数加入INIT内存区域。
在函数头中的“extern "C"”是指定编译器的编译方式,若不加此修饰,编译器则会按C++的编译方式来编译,会导致编译错误。
NTSTATUS是函数的返回状态,用来检测函数的状态是否正确,常用的NTSTATUS 值有:
#define STATUS_SUCCESS
#define STATUS_BUFFER_OVERFLOW
#define STATUS_UNSUCCESSFUL
#define STATUS_NOT_IMPLEMENTED
#define STATUS_ACCESS_VIOLATION
#define STATUS_INVALID_HANDLE
#define STATUS_INVALID_PARAMETER
接着是函数参数中的IN修饰,该修饰是定义参数的类型,“IN”修饰表示是一个输入参数,“OUT”修饰表示是一个输出参数,“INOUT”修饰表示是一个输入输出参数。
接下来就得了解了解驱动程序中的第一个结构体:PDRIVER_OBJECT,该结构体我在帮助文档里找了半天也没找到,最后在“wdm.h”中找到了其定义:
typedef struct _DRIVER_OBJECT {
CSHORT Type;
CSHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
UNICODE_STRING DriverName;
PUNICODE_STRING HardwareDatabase;
PFAST_IO_DISPATCH FastIoDispatch;
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT;
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;
该结构体共有15个成员,这个结构体表示的是一个驱动对象,是驱动的一个实例,类似于用户模式下的线程句柄一类。该对象在DriverEntry函数中被始化,然后由内核中的I/O管理器来加载,确切的加载函数是IoCreateDevice。
下面要说说该结构体中的几个重要成员:
DeviceObject:这是一个设备对象的结构体。一个驱动程序会创建多个设备对象,每个设备对象都有指向下一个设备对象的指针,最后一个设备象的指针为空。此处的DeviceObject指向驱动程序的第一个设备对象,
DriverName:驱动名称。其数据类型为UNICODE_STRING,该字符串一般为“\\driver\\[驱动名称]”,UNICODE_STRING字符串的赋值用RtlInitUnicodeString函数。
DriverUnload:指定驱动卸载时使用的回调函数地址。
MajorFunction:该成员是一个PDRIVER_DISPATCH结构体组数指针,其定义如下:
__drv_functionClass(DRIVER_DISPATCH)
__drv_requiresIRQL(PASSIVE_LEVEL)
__drv_sameIRQL
typedef
NTSTATUS
DRIVER_DISPATCH (
__in struct _DEVICE_OBJECT *DeviceObject,
__inout struct _IRP *Irp
);
typedef DRIVER_DISPATCH *PDRIVER_DISPATCH;
每个指针指向一个函数,这个函数就是处理IRP的派遣函数。
FastIoDispatch:文件驱动中用到的派遣函数。
派遣函数相当于WIN32子系统下的事件响应函数,驱动程序的主要功能是负责处理IO请求,而绝大多数的IO请求是在派遣函数中处理的。关于IRP派遣函数的相关解释另作笔记。