NT驱动开发学习笔记003
来源:互联网 发布:淘宝店库存管理 编辑:程序博客网 时间:2024/05/19 18:40
题外话:
坚持写笔记,慢慢形成习惯,劳逸结合,Go,Go,Go。
NT驱动开发学习笔记三2011.05.05
NT驱动的卸载例程DriverUnload:
A driver's Unload routine, if supplied, should be named XxxUnload, where Xxx is a driver-specific prefix. The driver's DriverEntry routine must store the Unload routine's address in DriverObject->DriverUnload.
如上所说:
pDriverObject->DriverUnload = myDDKUnload;//注意命名
VOID myDDKUnload(INPDRIVER_OBJECTpDriverObject);
在myDDKUnload里的传入参数是一个驱动对象的指针。其中根据DRIVER_OBJECT的结构,里面有个成员 PDEVICE_OBJECT DeviceObject; 指向这个驱动的第一个设备,让后在DEVICE_OBJECT里面有个成员DEVICE_OBJECT *NextDevice; 指向下一个设备对象,然后就可以遍历链表这样遍历设备对象了。
之前在创建设备时候把设备对象指针、设备名称和设备的符号链接都保存在DeviceExtension 这个结构里了,只要获取这个结构的信息后,删除设备就变得容易了。
pDeviceExtension = (PDEVICE_EXTENSION)pNextDevObj->DeviceExtension;
IoDeleteSymbolicLink(&(pDeviceExtension->szSymLinkName));
pNextDevObj = pNextDevObj->NextDevice;
IoDeleteDevice(pDeviceExtension->pDeviceObject);
NT驱动的派遣例程MajorFunction/MinorFunction:
IRP:
I/O Request Package,输入输出请求包。这是一个数据结构,上层应用程序与底层驱动程序通讯的时候,应用程序会发出I/O请求,操作系统把I/O请求转化为相应的IRP数据,然后根据类型传递到不同的派遣函数里面来处理。
MajorFunction/MinorFunction:
两个函数指针数组,分别记录了IRP的主类型和副类型,可以将IRP类型和派遣函数关联起来。注意:对于一些没有设置的IRP类型,系统默认这些IRP类型 和 函数_IopInvalidDeviceRequest 关联。就是在DriverEntry 之前,操作系统会用_IopInvalidDeviceRequest 的地址来填满整个MajorFunction 数组。
下面是派遣函数的原型,返回一个NT状态:
NTSTATUS (*PDRIVER_DISPATCH)(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp);
由于这是初探,所以就对派遣函数做一个简单的处理吧:
//设置IRP完成状态
pIrp->IoStatus.Status = ntStatus;
//设置IRP操作了多少字节
pIrp->IoStatus.Information = 0;
//处理IRP,这里指明了线程的恢复优先级为不增加优先级IO_NO_INCREMENT
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
优先级的概念的理解:
以ReadFile这个WIN32 API函数为例,看看它的内部操作:
①ReadFile 调用 ntdll 中的 NtReadFile。(其中ReadFile 是 WIN32 API,ntdll中的NtReadFile 是 Native API)。
②ntdll 中的 NtReadFile 进入到 Kernel Model(内核模式),调用 SSDT(系统服务描述表)中指出的 NtReadFile。
③系统服务函数 NtReadFile 创建了IRP_MJ_WRITE 类型的IRP,然后把这个IRP发到驱动程序的派遣函数中。
④在派遣函数中一般会用IoCompleteRequest将IRP请求结束,而在IoCompleteRequest里会设置等待事件,“睡眠”的线程恢复运行。
理解:
这里一开始会很难理解,想想ReadFile在读一个很大很大的文件(或设备)的时候,ReadFile是不能立刻返回的,而是会去等待一段时间,这段时间就称为睡眠的时间,当IRP请求结束的时候,这个“睡眠”的线程会被唤醒。
所以优先级可以让一些阻塞的线程优先恢复运行,这是很重要的,例如键盘、鼠标等设备,你在读文件的时候,他们不是也能很快的响应么?实际比这样想更复杂。
NT驱动中代码中断级的基本理解:
平时在用户模式下,所有的程序都是在同一个中断级,所以一般人都对这个概念没有什么感觉。
Windows把中断级扩展成了32个中断级别(IRQL)。其中0~2级别,即是PASSIVE_LEVEL 到 DISPATCH_LEVEL 级别为软中断级,3~31级别为硬件中断级。优先级0~31,级别逐渐升高。
对于软中断级,一般的线程都是运行在PASSIVE_LEVEL下的,负责调度线程的内核代码是运行在DISPATCH_LEVEL下的。就是说,DISPATCH_LEVEL下的线程是一种不会被切换的线程,想线程不被切换,就要从PASSIVE_LEVEL 提高到 DISPATCH_LEVEL。硬件的中断级都比软件的高,所以运行的线程都会被硬件中断(DIRQL)所打断,这就是为什么OllyDbg这些调试软件下的硬件中断可以过驱动保护下断了。
由于函数如果在一些不对应的中断级运行,就会出现错误,所以在调用内核API之前,都要查WDK文档来了解一个内核API的中断级,要养成这个习惯。
DISPATCH_LEVEL 下的线程使用的内存空间是不能出现缺页中断的,所以说 DISPATCH_LEVEL的调用就是不能出现在PAGE Section 中的,所以在预编译的时候要特别注意了。也可以在DISPATCH_LEVEL 代码中添加 PAGED_CODE() 宏来检测。
- NT驱动开发学习笔记003
- NT驱动开发学习笔记001
- NT驱动开发学习笔记002
- NT驱动开发学习笔记004
- NT驱动开发学习笔记005
- NT驱动笔记
- NT内核和驱动开发的基础知识-笔记
- NT内核和驱动开发的基础知识-笔记
- 驱动学习笔记2-用程序加载NT驱动程序
- 驱动开发学习笔记
- 驱动开发之 加载NT式驱动
- 驱动开发学习笔记1
- wince驱动开发学习笔记
- wince驱动开发学习笔记
- 驱动开发学习笔记1
- 【转帖】驱动开发学习笔记
- Linux驱动开发学习笔记
- 驱动开发学习笔记1
- (转)一些易忘的linux知识点
- Win7 xp 双系统安装说明(转)
- Android启动画面Splash
- C# 把数据集生成为JSON格式 并在使用Jquery 获取JSON数据
- JSON数据格式
- NT驱动开发学习笔记003
- how to copy a virtualbox vdi
- 从点点网说起
- java IO操作与字节流(五)对象序列化
- 在线hash密码破解网站列表,支持多种类型的hash密码
- 动态链接库笔记
- /res/raw & /assets 携带资源
- socket知识
- FlashObject详解:Flash的检测和嵌入javascript脚本