百度空间 | 百度首页 
               
 
查看文章
 
WDM(Windows Driver Model)学习(转)
2008-07-11 10:47

不同操作系统存在的驱动模式:
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)下:<windir>\system32\drives
     98/me/xp系统中windir=windows 2000系统中windir=winnt
   2.在注册表中如下位置添加如下的键值:
     HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\你驱动的名称
   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)<<2)|(Method))
回顾DeviceIoControl函数的第二个参数就可以知道什么是控制代码了^_^
下面是两个小的例子:
#define DEVIO_CallInt     CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define DEVIO_Test        CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS)


驱动的入口函数(DriverEntry):
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
1.创建设备对象
2.创建符号链接
3.设定功能函数的对应处理函数
}

如何在入口函数中建立设备对象和符号链接:
UNICODE_STRING ntNameString;
UNICODE_STRING win32NameString;
//create device
RtlInitUnicodeString(&ntNameString,L"\\Device\\TESTDRV");
IoCreateDevice(DriverObject,0,&ntNameString,FILE_DEVICE_UNKNOWN,0,FALSE,&deviceObject);
//create symbolic link
RtlInitUnicodeString(&win32NameString,L"\\DosDevices\\TESTDRV");
IoCreateSymbolicLink(&win32NameString,&ntNameString);

功能函数的定义:
操作系统载入时调用 DriverEntry
应用程序打开设备时调用 MajorFunction[IRP_MJ_CREATE]
应用程序关闭设备时调用 MajorFunction[IRP_MJ_CLOSE]
应用程序调用DeviceIoControl时调用 MajorFunction[IRP_MJ_DEVICE_COTROL]
操作系统卸载时调用 DriverUnload

DeviceControl函数对应的驱动函数的示例模板
NTSTATUS DeviceControl(IN PDEVICE_OBJECT fdo,IN PIRP irp)
{
PIO_STACK_LOCATION irpStack=IoGetCurrentIrpStackLocation(irp);
ULONG ControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;
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命令开始编译驱动程序

原文:http://hi.baidu.com/%CC%EC%D6%AE%B2%C3/blog/item/ad7186c42e18a0ad8226acaf.html

博客文章汇总:

如何科学饮水   供应WIFI(提供 wince linux下驱动)  

合肥市政府原副秘书长受贿240万被判13   百度C2C支付平台定名百付宝 域名地址昨曝光

LHC 的加速过程   什么是百度蜘蛛?百度爬虫是什么?    百度确定推C2C支付平台 电子商务大战一触即发   

无线音箱(出售)  

LINUX下无线网卡驱动程式安装的一般步骤  

云时代来临之云计算的四个显著特点 云计算时代来临 云计算到底指什么 随着安全云计算的热潮 您准备好了吗  

云计算的基本原理和概念  

发现一个靠点击广告就能赚美元的网站

Writing Linux LCD drivers

WinCELCD驱动程序编写指南

关于MODULE_PARM()  

Linux环境下USB的原理、驱动和配置2

Linux环境下USB的原理、驱动和配置1

腾讯发布QQ for Linux 1.0 Preview  

搜索引擎正在逐步抹杀人类的记忆和思考

[转载] Linux内核2.4.x的网络接口源码的结构  

Zigbee入门开发  

中国会面临金融战争的灭顶之灾吗?    不断增长的外汇储备,是中国政府的心病  

两粒电子的爱情  

zigbee简介  

银监会令深上报断供真相MTK是什么?  

[出售]WIFI模块,WIFI方案VT6656+RFUSB接口,MINIPCI接口   

鸟巢山寨机,玩的就是心跳   

ARM Bootloader的共性  

Jennic-zigbee开发套件

供应jennic无线模块 > jn5139高功率模块

吴宇森首度回应质疑萌萌是可爱的错误   

《赤壁》中的精彩与搞笑  

日本第一钻石王老五”--青山光司 日本第一钻王老五”--青山光司  

谁来拯救中国3760亿美元财富  

什么是无线网卡?

电磁辐射会失忆

中国产山寨手机热销巴基斯坦 难定位恐怖分子  

Zigbee标准可能成为自动化的未来动力

无线网络知识收集 无线增益天线认识和选购  

功率放大器"增益放大器"的区别   

无线问题面面观

噪声与信噪比  

zigbee软件设计  

什么是ZigBee无线网络?  

PLC 电力载波通信  

Introduction to IT800D  

超外差和超再生模块有何区别?  

飞弹发射失败怎么办?用 Photoshop 补一枚上去!   

Linux Driver Model()  

Power   Management in the Linux Driver Model(2.6.14)()  

WDM(Windows Driver Model)学习()  

Google问:手机还能拿来做什么?   

USB Dongle VT6656   

IEEE1394  

接收灵敏度   

JN5139 Wireless   Microcontroller  

JN5139-xxx-M02 高功率模块   

ZigBee架构WG议长:ZigBee与蓝牙可以共存  

基于ZigBee的无线网络技术及其应用  

Zigbee可能成为自动化的未来动力  

zigbee简介  

JN51xx开发套件  

ZigBee网络层


类别:默认分类 | 添加到搜藏 | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu