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请求会传递许多个设备才能完成,所以每次中转都会留一个栈空间,用于保存中间参数.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 技术原理 何为符号链接?符号链接是一个别名,可以指向任意一个有名字的对象. ZwCreateFile 不但可以打开...
    f675b1a02698阅读 625评论 0 0
  • 设备绑定的内核API之一 驱动 --> 生成多个 --> 设备对象 --> 对应 --> 真实的一个设备 wind...
    f675b1a02698阅读 712评论 0 0
  • 原文链接1、驱动对象:一个驱动对象代表了一个驱动程序。或者说一个内核模块。驱动对象的结构如下(这个结构的定义取自 ...
    Quinton_Lau阅读 1,689评论 0 0
  • 引言 总结一下最近设备驱动的学习成果,记录一下心得。文章里穿插记录字符设备驱动的相关知识。 硬件相关 一 ...
    three_eyelid阅读 1,216评论 1 1
  • 如果驱动程序要和应用程序通信,那么要生成一个设备对象. 设备对象和分发函数构成了整个内核体系的基本框架. 设备对象...
    f675b1a02698阅读 1,289评论 0 0