@网络老鼠技术小屋

网络老鼠技术小屋-涂飞平的博客空间

WDM(Windows Driver Model)学习笔记 [原]

12 年前 0

WDM(Windows Driver Model)学习笔记

不同操作系统存在的驱动模式:
NT4 KMD(Kernel Model Driver)
Win95 VxD(Virtual Device Driver)
Win98/Me VxD/WDM
Win2K/XP KMD,WDM

驱动的分层模型:
用户模式 - 应用程序
内核模式 - 驱动程序
硬件层 - IO端口/物理内存

建立驱动程序的环境要求:
1.必须装有Visual Studio 6
因为我们需要使用其编译器和链接器,当然,我们也可以使用它的编辑环境
2.必须安装有相应操作系统的DDK
因为DDK中含有驱动程序的链接库和头文件

驱动的载入方式:
1.静态载入
在操作系统启动的时候就开始载入到内存中,window98/me只有这种方式
2.动态/运行时载入
当程序需要驱动服务时候再载入,windows2000/xp支持静态和动态两种方式

静态载入技术:
1.将驱动程序文件拷贝到系统驱动目录(Windir)下:system32drives
98/me/xp系统中windir=windows 2000系统中windir=winnt
2.在注册表中如下位置添加如下的键值:
HKEY_LOCAL_MACHINESystemCurrentControlSetServices你驱动的名称
3.在驱动名称下增加如下的值:
ErrorControl=1(DWORD)
Type =1(DWORD)
Start =1(DWORD)
4.重启电脑就可以设置成功!

应用程序调用驱动的方式:

main()
{
CreateDriverService();//子过程,动态载入驱动程序到内核中
HANDLE h=OpenDriver();
DeviceIoControl(h,,,);//开始要求驱动做某些事情。这个是API
CloseHandle(h);//API
DeleteDriverService();//子过程,若时动态载入,必须卸载驱动
}
关键函数:DeviceIoControl()
BOOL DeviceIoControl(
HANDLE hDevice, //In -驱动程序的句柄
DWORD dwIoControlCode, //In -操作控制代码
LPVOID lpInBuffer, //In -输入数据缓冲区
DWORD nInBufferSize, //In -输入数据缓冲区的大小
LPVOID lpOutBuffer, //Out -输出数据缓冲区
DWORD nOutBufferSize, //In -输出数据缓冲区的大小
LPDWORD lpBytesReturned, //Out -输出的数据的数量
LPOVERLAPPED lpoverlapped //In -重叠IO模式选项

一个驱动程序所需要的文件:
makefile:所有的驱动程序都必须有这个文件,而且都是一样的。
Sources:驱动程序配置文件,包含了所有必须的信息
驱动程序的源代码

简单介绍一下Sources文件的内容:

TARGETNAME=TESTDRV #驱动的名称
TARGETTYPE=DRIVER #目标的类型
DRIVERTYPE=WDM #驱动的类型,还有诸如KMD之类的
TARGETPATH=. #目标文件导出目录

SOURCES = prog.cpp #源文件列表

控制代码的宏定义:
控制代码的宏定义是在devio.h头文件中定义的。

#define CTL_CODE( DeviceType,Function,Method,Access) (((DeviceType)<<16)|((Access)<< 14)|((Function)ULONG InputLength=irpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputLength=irpStack->Parameters.DrviceIoControl.OutputBufferLength;
PVOID WorkBuffer=(PVOID)irp->AssociatedIrp.SystemBuffer;
switch(ControlCode)
{
case DEVIO_CALLInt:return DoCallInt(irp);
case DEVIO_Test: return DoTest(irp);
default:
irp->IoStatus.Status=STATUS_INVALID_DEVICE_REQUEST;
irp->IoStatus.Information=0;
IoCompleteRequest(irp,IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
}
驱动程序的卸载:
当应用程序关闭设备(如果是动态载入的话)或者操作系统关闭的时候,操作系统会调用驱动程序的Unload函数,我们可以在这里将我们中间申请的资源释放掉。
下面是上面示例对应的卸载动作:
IoDeleteSymbolicLink(&win32NameString);
IoDeleteDevice(DriverObject->DeviceObject);
驱动程序与应用程序数据交换的三种模式:
复制模式:将用户程序的输入缓冲区按大小复制到系统空间中,我们可以通过irp->AssociatedIrp.SystemBuffer来访问这个缓冲区的系统备份,我们返回的数据也是放置在这块区域中,然后系统会按大小复制给用户的输出缓冲区。
映射模式:将用户程序的输入和输出缓冲区的物理内存都映射到系统空间中,然后我们就可以自由访问,由于他们同时也在用户区域映射,所以是一致的。
直接映射模式:这种模式什么也没有做,直接将用户程序的地址传递过来,由于驱动程序不一定在调用者的进程上下文中运行,所以这种方式要特别小心,如果能够确保在同一进程中运行,才能使用这种方式!

创建驱动的步骤:
1.点击DDK菜单中的checked或者free模式,启动相应的批处理文件初始化环境
2.进入我们驱动程序Sources文件所在目录
3.使用build命令开始编译驱动程序。

Sundy 2005

编写评论