记录驱动开发前的知识储备工作
参考我这篇:WIN10 驱动开发环境从0搭建
Windows Vista
是微软公司2006年11月30日正式发布的操作系统,2017年
4月11日,微软正式终止对Windows Vista的一切支持。
最早使用——>VXD (已经废弃)
Vista支持——>WDM
Vista及其以后——>WDF
: 意为Windows Driver Foundation,此模型比WDM更先进、合理,将WDF中关于电源、PnP等一些复杂的细节由微软实现,所以在此模型上开发驱动会比以前要简单。
在 Windows 操作系统中,WDM 驱动程序按名为驱动程序堆栈 的垂直调用序列分层。在 I/O 请求已通过操作系统的 I/O 管理器之后,堆栈中位于最顶层的驱动
程序通常会从
用户应用程序
接收这些请求。较低层的驱动程序通常与计算机硬件通信。
简单的驱动程序堆栈包括位于堆栈底部的总线驱动程序,该驱动程序用于处理总线特定的 I/O 操作,并枚举与总线相连的子设备。总线驱动程序上方通常有一个或多个设备特定的功能驱动程序。这些功能驱动程序处理与总线相连的设备的 I/O 操作。筛选器驱动程序可位于功能驱动程序上方,也可以位于总线驱动程序和功能驱动程序之间。正在运行的系统具有多个驱动程序堆栈,可支持不同类型的设备。
每个驱动程序堆栈都支持一个或多个设备堆栈。设备堆栈是一组根据 WDM 定义的 DEVICE_OBJECT 结构创建的设备对象。
每个设备堆栈都表示一台设备。每个驱动程序为其每台设备创建一个设备对象,并将每个设备对象附加到设备堆栈。当插入和拔出设备以及每当重新引导系统时,将创建和删除设备堆栈。
总线驱动程序在检测到已插入或拔出子设备时会通知即插即用 (PnP) 管理器。作为响应,PnP 管理器要求总线驱动程序为连接到父设备(即总线)的每台子设备创建一个物理设备对象 (PDO)。PDO 随即成为设备堆栈的底部。
接下来,PnP 管理器加载功能驱动程序和筛选器驱动程序以便支持每台设备(如果尚未加载这些驱动程序),然后 PnP 管理器会调用这些驱动程序,使每个驱动程序都可以创建一个设备对象并将该设备对象添加到设备堆栈的顶层。功能驱动程序创建函数设备对象 (FDO),筛选器驱动程序创建筛选器设备对象(筛选器 DO)。
I/O 管理器将 I/O 请求发送到设备的驱动程序时,它会将该请求传递到创建设备堆栈中的顶层设备对象的驱动程序。
I/O 管理器通过创建 I/O 请求数据包 (IRP),将应用程序的 I/O 请求发送到驱动程序。IRP 可包含执行 I/O 操作(如读/写操作)的请求或执行 I/O 控制 (IOCTL) 操作(如返回状态)的请求。此外,PnP 管理器还会创建表示驱动程序必须执行的 PnP和电源管理操作的 IRP,并将这些 IRP 发送到驱动程序。
I/O 管理器通常在用户应用程序请求读取或写入操作时创建读取或写入 IRP。I/O 管理器将 IRP 传递到位于驱动程序堆栈顶层的驱动程序,该驱动程序或者为该请求提供服务,或者将该请求传递到下一层驱动程序。某些请求会传输到堆栈底部,而某些请求则完全由较高层的驱动程序处理。
每当驱动程序接收 IRP 时,该程序还会接收一个指向某个设备对象的指针,该设备对象表示必须处理该操作的设备。因此,驱动程序堆栈中的驱动程序使用设备对象确定应将特定请求传输到插入的哪个设备。
基于框架的驱动程序通常不会直接访问 IRP。内核模式驱动程序框架将表示读取、写入和设备 I/O 控制操作的 WDM IRP 转换为驱动程序在 I/O 队列中接收的框架请求对象。框架在内部处理 PnP 和电源管理 IRP,并使用事件回调函数向驱动程序发送 PnP 和电源事件通知。
以WDM为基础进行建模和封装,降低开发难度,改动如下:
驱动程序与操作系统交互工作
交给框架内封装
的方法(函数)完成;全局唯一标识符(GUID,Globally Unique Identifier)是一种由算法生成的二进制长度为128位的数字标识符,用于唯一标识一个任意计算机。GUID 的总数达到了2128(3.4×1038)个,所以随机生成两个相同GUID的可能性非常小,但并不为0。所以,用于生成GUID的算法通常都加入了非随机的参数(如时间
),以保证这种重复的情况不会发生。
#include
#include
//--生成GUID
const char* newGUID()
{
static char buf[64] = {0};
GUID guid;
if (S_OK == ::CoCreateGuid(&guid))
{
_snprintf(buf, sizeof(buf)
, "{%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}"
, guid.Data1
, guid.Data2
, guid.Data3
, guid.Data4[0], guid.Data4[1]
, guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5]
, guid.Data4[6], guid.Data4[7]
);
}
return (const char*)buf;
}
int main(int argc, char* argv[])
{
//--COM
CoInitialize(NULL);
printf(newGUID());
printf("\n");
//--COM
CoUninitialize();
return 0;
}
仅低中断
级别的例程可以访问的,而非分页内存则是各个中断级别
的例程都可以使用的;