2.3重要的数据结构 - 驱动对象和设备对象

Windows内核中把驱动,设备,文件等都称为"对象",在系统启动后,这些对象都在内存中.

一个驱动对象(DRIVER_OBJECT)代表了一个驱动程序,或者是内核模块.

设备对象(DEVICE_OBJECT)是在内核中唯一接收请求的实体.大部分消息都是以请求(IRP)方式传递的,而任何一个请求都是发送被某个设备对象的.设备对象是驱动对象结构的第三个参数对象.

内核程序是以一个驱动对象表示的,所以一个设备对象总是属于一个驱动对象.

驱动对象结构:

typedef struct _DRIVER_OBJECT{

CSHORT Type;

CSHORT Size;

//设备对象,是一个设备对象链表的开始.

PDEVICE_OBJECT DeviceObject;

ULONG Flags;

//驱动在内核空间的开始地址和大小

PVOID DriverStart;

ULONG DriverSize;

PVOID DriverSection;

PDRIVER_EXTENSION DriverExtension;

//驱动的名字,确定一个I/O请求被绑定的驱动程序的名称

UNICODE_STRING DriverName;

//指向注册表中的硬件信息的路径

PUNICODE_STRING HardwareDatabase;

//快速IO分发函数的入口,数组的可选指针,通过参数单独调用驱动程序执行,而不是使用IRP(操作系统内核的一个数据结构,应用程序与驱动程序进行通信需要通过IRP包)调用机制,这些功能只能被用户同步IO或者文件缓存

PFAST_IO_DISPATCH FastIoDispatch;

//驱动程序初始化

PDRIVER_INITIALIZE DriverInit;

//特定入口,

PDRIVER_STARTIO DriverStartIo;

//驱动卸载函数

PDRIVER_UNLOAD DriverUnload;

//普通分发函数(IRP)

PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];

} DRIVER_OBJECT;

设备对象结构:

typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECT {

CSHORT Type;

USHORT Size;

//引用计数

LONG ReferenceCount;

//设备所属驱动对象

struct _DRIVER_OBJECT *DriverObject;

//下一个设备对象,一个驱动对象中可能有许多个设备,这些设备用指针连接,作为单向链表

struct _DEVICE_OBJECT *NextDevice;

struct _DEVICE_OBJECT *AttachedDevice;

struct _IRP *CurrentIrp;

PIO_TIMER Timer;

ULONG Flags;

ULONG Characteristics;

__volatile PVPB Vpb;

PVOID DeviceExtension;

//设备类型

DEVICE_TYPE DeviceType;

//IRP栈的大小

CCHAR StackSize;

union {

LIST_ENTRY ListEntry;

WAIT_CONTEXT_BLOCK Wcb;

} Queue;

ULONG AlignmentRequirement;

KDEVICE_QUEUE DeviceQueue;

KDPC Dpc;

ULONG ActiveThreadCount;

PSECURITY_DESCRIPTOR SecurityDescriptor;

KEVENT DeviceLock;

USHORT SectorSize;

USHORT Spare1;

struct _DEVOBJ_EXTENSION  *DeviceObjectExtension;

PVOID  Reserved;

} DEVICE_OBJECT;

IRP向设备对象发送请求时会被驱动对象的分发函数捕获,被其中一个调用

分发函数原型

NTSTATUS MyDispatch(PDEVICE_OBJECT device, PIRP irp);

参数1是请求的目标设备,参数2是IRP请求的指针

IRP的结构

IRP是一个内核数据结构,结构非常复杂,因为要表示无数中实际请求.

typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP 共300多行代码,位于 wdm.h 24795行

其中

PMDL MdlAddress; 内存描述符表链表指针,是一个缓冲区,内核请求都需要一个缓冲区,用来保存数据

union {

struct _IRP *MasterIrp;

__volatile LONG IrpCount;

PVOID SystemBuffer;

} AssociatedIrp; 该共用体也是一个系统缓冲,比 MdlAddress 稍简单表示缓冲的方式,IRP会根据IO的请求方式选择其中的某一个.

IO_STATUS_BLOCK IoStatus; IO状态,请求完成之后的返回情况放在这里.

CHAR StackCount; IRP栈空间大小

CHAR CurrentLocation; IRP当前栈空间

__volatile PDRIVER_CANCEL CancelRoutine; 用来取消一个未决(没有执行完成?)请求的函数

PVOID UserBuffer; 与上面两个一样可以表示缓冲区,但特性稍有不同

union {

struct {

union {

KDEVICE_QUEUE_ENTRY DeviceQueueEntry;

struct {

PVOID DriverContext[4];

} ;

} ;

//发出这个请求的线程

PETHREAD Thread;

PCHAR AuxiliaryBuffer;

struct {

LIST_ENTRY ListEntry;

union {

//IRP栈空间元素

struct _IO_STACK_LOCATION *CurrentStackLocation;

ULONG PacketType;

};

};

PFILE_OBJECT OriginalFileObject;

} Overlay;

KAPC Apc;

PVOID CompletionKey;

} Tail;

因为IRP请求会传递许多个设备才能完成,所以每次中转都会留一个栈空间,用于保存中间参数.

你可能感兴趣的:(2.3重要的数据结构 - 驱动对象和设备对象)