ImageVerifierCode 换一换
格式:DOC , 页数:13 ,大小:64KB ,
资源ID:1322300      下载积分:15 文钱
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,省得不是一点点
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.wenke99.com/d-1322300.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(深度剖析WinPcap之(三)所涉及的Windows驱动基础知....DOC)为本站会员(天***)主动上传,文客久久仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知文客久久(发送邮件至hr@wenke99.com或直接QQ联系客服),我们立即给予删除!

深度剖析WinPcap之(三)所涉及的Windows驱动基础知....DOC

1、深度剖析 WinPcap 之(三)所涉及的 Windows 驱动基础知识(1)1.1 Windows 驱动的基础知识本节主要描述在 WinPcap 的 NPF 中经常使用一些编写 Windows 驱动程序所需掌握的部分基础知识,以便于后面的理解。1.1.1 驱动对象(DRIVER_OBJECT)每个驱动程序都有唯一的驱动对象与之对应,该驱动对象在驱动程序被加载时由内核的对象管理程序所创建。驱动对象用 DRIVER_OBJECT 数据结构表示,它作为驱动程序的一个实例被内核加载,对一个驱动程序内核 I/O 管理器只加载一个实例。驱动对象数据结构在 wdm.h 文件中的定义如下。typedef s

2、truct _DRIVER_OBJECT CSHORT Type;CSHORT Size;/*DeviceObject 为每个驱动程序所创建的一个或多个设备对象链表,*Flags 提供一个扩展的标识定位驱动对象*/PDEVICE_OBJECT DeviceObject;ULONG Flags;/*下列各成员字段描述驱动程序从哪儿被加载*/PVOID DriverStart;ULONG DriverSize;PVOID DriverSection;PDRIVER_EXTENSION DriverExtension;/*DriverName 成员被错误日志线程用来*确定一个 I/O 请求越界的驱动

3、名称*/UNICODE_STRING DriverName;/*指向注册表中硬件信息的路径*/PUNICODE_STRING HardwareDatabase;/*如果驱动支持“fast I/O”,*就指向一个“fast I/O”的派遣函数数组*/PFAST_IO_DISPATCH FastIoDispatch;/*描述该特定驱动的入口点。*主函数(major function)派遣函数表必须是对象最后的成员,*因此它仍然是可扩展的*/PDRIVER_INITIALIZE DriverInit;PDRIVER_STARTIO DriverStartIo;PDRIVER_UNLOAD Drive

4、rUnload;PDRIVER_DISPATCH MajorFunctionIRP_MJ_MAXIMUM_FUNCTION + 1; DRIVER_OBJECT;typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;下面分别描述驱动对象中驱动程序可访问的成员。PDEVICE_OBJECT DeviceObject每个驱动对象会有一个或多个设备对象。每个设备对象都有一个指针(NextDevice)指向下一个驱动对象,最后一个设备对象指向空。此处的DeviceObject 指向驱动对象的第一个设备对象。该成员在成功调用IoCreateDevice 后自动更新。

5、一个驱动程序使用该程成员与设备对象(DEVICE_OBJECT)的 NextDevice 可遍历给驱动对象的所有设备对象。在驱动被卸载的时候,需要遍历每个设备对象,并将其删除。PUNICODE_STRING HardwareDatabase指向注册表中硬件配置信息的路径,用 UNICODE 字符串表示。该字符串一般为REGISTRYMACHINEHARDWAREDESCRIPTIONSYSTEM。PFAST_IO_DISPATCH FastIoDispatch指向一个定义驱动快速 I/O 结构体的入口点,该成员只用于文件系统驱动与网络传输驱动。PDRIVER_INITIALIZE Driver

6、Init是 DriverEntry 例程的入口点,由 I/O 管理器设置。PDRIVER_STARTIO DriverStartIo是 Startl0 例程的的入口点,如果需要,由 DriverEntry 例程设置,否则为 NULL。PDRIVER_UNLOAD DriverUnload指向驱动卸载时所用回调函数的入口点。PDRIVER_DISPATCH MajorFunctionIRP_MJ_MAXIMUM_FUNCTION+1一个函数指针数组, 数组 MajorFunction 中的每个成员保存着一个指针,每一个指针指向一个处理对应 IRP(IRP_MJ_XXX)的派遣函数(Dispatc

7、hXxx)。每个派遣函数(DispatchXxx)声明如下:NTSTATUS(*PDRIVER_DISPATCH) (IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);1.1.2 设备对象(DEVICE_OBJECT)设备对象保存设备特征和状态的信息。一个设备对象表示一个逻辑的、虚拟的或物理的设备,由一个驱动对象操控设备对象的 I/O 请求。每一个内核模式的驱动必须创建设备对象,通过调用 IoCreateDevice 一次或多次。每个驱动程序会创建一个或多个设备对象,用 DEVICE_OBJECT 数据结构表示。每个设备对象有一个指针(NextDevice

8、)指向下一个设备对象,从而形成一个设备链表。设备链表第一个设备是由驱动对象结构体中 DeviceObject 指明的。设备对象数据结构在 wdm.h 文件中的定义如下。typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECTCSHORT Type;USHORT Size;LONG ReferenceCount;struct _DRIVER_OBJECT *DriverObject;struct _DEVICE_OBJECT *NextDevice;struct _DEVICE_OBJECT *Attach

9、edDevice;struct _IRP *CurrentIrp;PIO_TIMER Timer;ULONG Flags;ULONG Characteristics;_volatile PVPB Vpb;PVOID DeviceExtension;DEVICE_TYPE DeviceType;CCHAR StackSize;union LIST_ENTRY ListEntry;WAIT_CONTEXT_BLOCK Wcb; Queue;ULONG AlignmentRequirement;KDEVICE_QUEUE DeviceQueue;KDPC Dpc;/*下列成员是为支持文件系统的互斥操

10、作,*为了对文件系统处理线程使用设备的计数保持跟踪*/ULONG ActiveThreadCount;PSECURITY_DESCRIPTOR SecurityDescriptor;KEVENT DeviceLock;USHORT SectorSize;USHORT Spare1;struct _DEVOBJ_EXTENSION *DeviceObjectExtension;PVOID Reserved; DEVICE_OBJECT;typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT;下面分别描述设备对象中驱动程序可访问的成员。PDRIVER_OBJEC

11、T DriverObject指向驱动程序中的驱动对象。同属于一个驱动程序的驱动对象指向的是同一个驱动对象。PDEVICE_OBJECT NextDevice指向下一个设备对象。这里的下一个设备对象是同一个驱动程序创建的若干设备对象。每个设备对象根据 NextDevice 域形成链表,从而可以遍历每个设备对象。在每次成功调用 IoCreateDevice 后 I/O 管理器更新该链表。在驱动被卸载的时候,需要遍历该链表,删除每个设备对象。PIRP CurrentIrp如果驱动使用 Startl0 例程时,此成员指向当前 IRP 结构。否则为 NULL。 ULONG Flags此成员是一个 32

12、位昀无符号整型,每个位有不同的含义。通过位或操作为新创建的设备对象设置不同的特性。ULONG Characteristics当驱动程序调用 IoCreateDevice 时,设置下列一个合适的值:FILE_REMOVABLE_MEDIAFILE_READ_ONLY_DEVICEFILE_FLOPPY_DISKETTEFILE_WRITE_ONCE_MEDIAFILE_DEVICE_SECURE_OPENPVOID DeviceExtension指向设备扩展对象。设备扩展对象是由程序员在驱动中自行定义的结构体,结构体的大小在调用 IoCreateDevice 时设置。每个设备都会指定一个设备扩展

13、对象,设备扩展对象记录的是特别定义的结构体。在驱动程序中应该尽量避免全局变量的使用,因为全局变量涉及不容易同步的问题,解决的办法可将全局变量存储在设备扩展中。DEVICE_TYPE DeviceType指明设备的类型,由 IoCreateDevice 设置。根据设备需要填写相应的设备类型。.CCHAR StackSize在多层驱动的情况下,驱动与驱动之间形成类似堆栈的结构。IRP 会依次从最高层传递到最底层。StackSize 就是指定发送到该驱动的 IRP 在堆栈位置的最小层数。IoCreateDevice 在一个新创建的设备对象中设置该成员。ULONG AlignmentRequireme

14、nt设备在大容量传输的时候,为了保证传输速度需要内存对齐。每个设备对象在它新创建的设备对象中设置该成员。1.1.3 设备扩展(_DEVICE_EXTENSION)设备对象记录设备的“通用”信息,而另外一些“特殊”信息记录在设备扩展中。设备扩展由程序员自行定义,指定内容与大小,由 I/O 管理器创建,保存在非分页内存中。在驱动程序中,尽量避免使用全局函数,因为全局函数往往导致函数的不可重入性。一个解决办法就是将全局变量以设备扩展的形式存储,并加以适当的同步保护措施。WinPcap 中 NPF 的设备扩展结构体,主要用于存储每个被 NPF 绑定的适配器的一些信息,结构体定义如下:typedef s

15、truct _DEVICE_EXTENSION /适配器名称NDIS_STRING AdapterName;/设备导出的名称,也就是通过 WinPcap 应用程序使用该名称来打开该适配器PWSTR ExportString; DEVICE_EXTENSION, *PDEVICE_EXTENSION;1.1.4 IRP 与派遣函数驱动程序的主要功能是负责处理 l/O 请求,大部分 1/0 请求是在派遣函数中处理的。IRP 的处理机制类似 Windows 应用程序中的“消息处理”机制。用户空间对驱动程序的所有 1/0 请求,全部由操作系统转化为一个 IRP 数据结构,不同的 IRP 数据会被“派遣

16、”到不同的派遣函数中,在派遣函数中处理 IRP。 IRP 是 Windows 内核中输入输出请求包(I/O Request Package,IRP)的缩写。IRP 具有两个基本属性:MajorFunction 与 MinorFunction,分别记录 IRP的主功能和子功能。操作系统根据 MajorFunction 将 IRP“派遣”到不同的派遣函数中,在派遣函数中还可以根据 MinorFunction 继续判断该 IRP 属于哪种子功能。一般来说驱动程序都是在 DriverEntry 函数中注册派遣函数的。在DriverEntry 的驱动对象 pDriverObject 中,有个函数指针数组

17、MajorFunction,每个数组元素都记录着一个派遣函数的地址。通过设置该数组,可以将不同类型的 IRP 和对应的派遣函数关联起来。大部分的 IRP 都源于文件 I/O 处理的 API,如CreateFile、ReadFile、WriteFile、CloseHandle 等函数会使操作系统产生IRP_MJ_CREATE、IRP_MJ_READ、IRP_ MJ_WRITE、IRP_MJ_CLOSE 等不同类型的IRP,这些 IRP 会被传送到驱动程序中,调用对应的派遣函数。此外,内核中的文件 I/O 处理函数,如 ZwCreateFile、ZwReadFile、ZwWriteFile、ZwC

18、lose 也同样会创建 IRP_MJ_CREATE、IRP_MJ_READ、lRP_MJ_WRITE、IRP_MJ_CLOSE 等IRP,并将 lRP 传送到驱动程序中,调用对应的派遣函数。 处理 IRP 最简单的方法就是在相应的派遣函数中,将 IRP 的状态设置为成功,然后结束 IRP 的请求,并让派遣函数返回成功。结束 IRP 的请求使用函数IoCompleteRequest。下面为 NPF 中 NPF_Close 的代码,为处理 IRP_MJ_CLOSE类型 IRP 的派遣函数。NTSTATUS NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PI

19、RP Irp)Irp-IoStatus.Status = STATUS_SUCCESS;Irp-IoStatus.Information = 0;IoCompleteRequest(Irp, IO_NO_INCREMENT);return STATUS_SUCCESS;函数 NPF_Close 设置 IRP 的完成状态为 STATUS_SUCCESS。这样发起请求的 API(如 CloseHandle)将会返回 TRUE。相反,如果将 IRP 的完成状态设置为不成功,发起 I/O 请求的 API(如 CloseHandle)将会返回 FALSE。出现该情况时,可以使用 GetLastError

20、 API 获得错误代码。所得的错误代码会和 IRP 设置的状态一致。除了设置 IRP 的完成状态,函数还要设置这个 IRP 请求操作了多少字节。在本代码中,将操作字节数设置成了 0。如果是 ReadFile 产生的 IRP,这个字节数代表从设备读了多少字节。如果是 WriteFile 产生的 IRP,这个字节数代表对设备写了多少字节。最后函数通过 IoCompleteR0quest 函数将 IRP 请求结束。IoCompleteRequest 的声明如下:VOID IoCompleteRequest(IN PIRP Irp,IN CCHAR PriorityBoost);参数 Irp 代表需要

21、被结束的 IRP。参数 PriorityBoost 代表线程恢复时的优先级别,指的是被阻塞的线程以何种优先级恢复运行。一般情况下,优先级设置为 IO_NO_INCREMENT。1.5.1 同步处理Windows 是个多任务抢占式的操作系统,如果没有同步机制的控制,所有的线程会任意运行。如果多个线程要求操作同一个资源,这时就需要同步处理。如果驱动程序没有很好地处理同步问题,程序会出错误、操作系统的性能下降、甚至出现死锁等现象。1.5.1.1 自旋锁自旋锁是一种同步处理机制,它能保证某个资源只能被一个线程所拥有,可用于驱动程序的同步处理。自旋锁的作用一般是使各派遣函数之间同步。初始化的自旋锁处于解

22、锁状态,这时它可以被程序“获取”。“获取”后的自旋锁处于锁住状态,不能被再次“获取”。锁住的自旋锁必须被“释放”后,才能再次被 “获取”。如果自旋锁已被锁住,这时有程序申请“获取”这个自旋锁,程序则处于“自旋”状态。所谓自旋状态,就是不停地询问是否可以“获取”自旋锁。自旋锁不同于线程中的等待事件。在线程中如果等待某个事件,操作系统会使这个线程进入休眠状态,CPU 会运行其它的线程。而自旋锁则不同,CPU 不会切换到别的线程,而是让这个线程一直“自旋”等待。因此,对自旋锁占用时间不宜过长,否则会导致申请自旋锁的其它线程处于自旋,浪费 CPU 的处理时间。NDIS 库提供的自旋锁可用来在相同 IR

23、QL 的线程之间同步访问共享资源,当共享资源的两个线程运行在不同的 IRQL 时,NDIS 库提供一种机制临时提升低 IRQL 代码的 IRQL,从而达到对共享资源的串行访问。NDIS 库的自旋锁用 NDIS_SPIN_LOCK 数据结构表示。使用自旋锁前,首先对其初始化,可使用 NdisAllocateSpinLock 函数。VOID NdisAllocateSpinLock( IN PNDIS_SPIN_LOCK SpinLock );申请获得自旋锁可以使用 NdisAcquireSpinLock 函数。VOID NdisAcquireSpinLock( IN PNDIS_SPIN_LOC

24、K SpinLock );释放自旋锁使用 NdisReleaseSpinLock 内核函数,VOID NdisReleaseSpinLock(IN PNDIS_SPIN_LOCK SpinLock );下面的代码为 WinPcap 中使用自旋锁的实例:NDIS_SPIN_LOCK WriteLock;/在_OPEN_INSTANCE 声明自旋锁NdisAllocateSpinLock(/初始化自旋所NdisAcquireSpinLock(/ 申请获得自旋锁if(Open-WriteInProgress)NdisReleaseSpinLock( / 释放自旋锁SET_FAILURE_UNSUCC

25、ESSFUL();break;elseOpen-WriteInProgress = TRUE;NdisReleaseSpinLock(/ 释放自旋锁1.1.5.2 用户模式的等待在应用程序中,可以使用 WaitForSingleObject 等待一个同步对象。WaitForSingleObject 函数声明如下:DWORD WaitForSingleObject( HANDLE hHandle, /同步对象句柄DWORD dwMilliseconds /等待时间);第二个参数 dwMiUiseconds 是等待时间,单位为毫秒。同步对象有两种状态,一种是激发状态,一种是未激发状态。如果同步对象

26、处于未激发状态,WaitForSingleObject 则进入休眠,等待同步对象被激发。如果同步对象在指定的等待时间内,还没有处于激发状态,则自动停止休眠。dwMilliseconds 也可以设定为 INFINITE这表示无限期地等待下去。另外,dwMilliseconds 也可以为 0,其作用是强迫操作系统将当前线程切换到其他线程。1.1.5.3 用户模式的事件事件是一种典型的同步对象。用户模式下的事件和内核模式的事件对象紧密相连。在使用事件之前,需要对事件进行初始化,使用 CreateEvent 函数。HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpE

27、ventAttributes, / 安全属性BOOL bManualReset, / 复位方式BOOL bInitialState, / 初始化状态LPCTSTR lpName / 对象名称);CreateEvent 函数会使操作系统创建一个内核事件对象。CreateEvent 返回的句柄值就代表了这个内核事件对象。应用程序无法获得这个内核事件对象的指针,而用一个句柄(一个 32 位的无符号整数)代表事件对象。一般情况下,CreateEvent 的安全属性设置为 NULL。它的第二个参数 bManualReset,表示创建的事件是否是手动模式。如果是手动模式的事件,事件处于激发状态后,需要手动

28、设置才能回到未激发状态。如果是自动模式,当事件处于激发状态后,遇到任意一个等待(如 WaitForSingleObject),则自动变回未激发状态。下面的代码为 WinPcap 中创建一个事件的实例:HANDLE hEvent;hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);1.1.5.4 NDIS 库提供的事件NDIS 库的事件用 NDIS_EVENT 数据结构表示。使用事件前,首先对其初始化,可使用 NdisInitializeEvent 函数。VOID NdisInitializeEvent(IN PNDIS_EVENT Event);把调用者

29、置为等待状态,直到给定的事件为信号状态,或等待超时,可以使用 NdisWaitEvent 函数。BOOLEAN NdisWaitEvent(IN PNDIS_EVENT Event,IN UINT MsToWait); 把一个给定的事件设为信号状态 ,可使用 NdisSetEvent 函数,VOID NdisSetEvent(IN PNDIS_EVENT Event);清除一个给定的事件的信号状态,可使用 NdisResetEvent 函数,VOID NdisResetEvent(IN PNDIS_EVENT Event);下面的代码为 WinPcap 中使用 NDIS 库事件的实例:NDIS_EVENT NdisWriteCompleteEvent;NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)NdisInitializeEvent(NTSTATUS NPF_Write(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。