【文章标题】: 真正的驱动入门()[附小程序代码]
【文章作者】: CCDeath![]()
![]()
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
很多初学驱动入门比较难.最后发现“难”是难在配置方面和WDM型几个比较抽象的概念。偶学了有半个月吧,很多网上写
的不全,终于了解比较简单的整个流程了...
1.书籍推荐 有个大侠推荐的...这些书籍可以从看雪、电骡、迅雷、驱网、得益网下得到....
前提必须会点c语言、MFC框架[测试的时候,弄一个比较漂亮的截面:-)]
《windows 2000 内部揭密>>--------------------------------------这里面可以学到什么是IRP、内存管理、文件系统之类
《驱动模型设计>>-----------------------------------------------好详细的一本书.
《windows 2000\xp wdm 设备驱动程序设计>>-----------------------使用DS开发,无论如何使用里面的工具会更帅...说真的...
《DDK文档及DDK里面的例子>>DDK开发包----------------------------安装的时候要注意,一定把她及所在例子钩起来,不然
你找不到DDK文档的....
www.driverdevelop.com------------------------------------------人气有点低,不够还很很不错..,专业人士较多
www.pediy.com--------------------------------------------------人气很高,很热情,各个领域人的都有.
2.
虚拟机(VMWare等):建议装Windows 2000.iso 不然配置会出现很多的错误,同时候用softice或者windbg,避免OS蓝屏,把
时间浪费在开机上...
DriverStudio3.2:开发工具包.如果喜欢在DDK环境下,也可以利用这个开发包里面的一些工具:DriverMonitor、
EAZDriverInstaller,softice
Windbg:中文教程较少.但是跟微软走,比较有保障.就怕他最后要收钱...双机调试.
VC6.0++:这个要先安装,然后才安装DDK,这个顺序可不能乱..
DDK:没得说..VC开发工具包含这个目录,才能弹出提示符号比如 this->点这边才能弹出。.
在工具->选项->目录->H:\WINDDK\2600\INC\DDK\WXP.有时候H:\WINDDK\2600\INC\DDK不能识别,不能this->
VC助手:这个工具一定要装,很好用的。很快捷,掉渣...
注意:如果配置上还有问题的话,百度将会是你最后的归宿...
3.先解决简单概念问题后解决WDM模型的概念
a.OS:时间分片,但是记得给每个线程的时间CPU不一定相同.
#include "windows.h"
#include "iostream.h"
void main()
{
HANDLE hThread;
hThread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL);//不写ThreadProc了...懒
CloseHandle(hThread);//一.关闭线程句柄,线程可没终止.2.主线程main对线程引用不感兴趣3. 前为n=0.
//当执行CreateThread() n+1;hThread=CreateThread() n+1+1
// 所以现在计数可是n(n=0)+2=2;当关闭CloseHandle(hThread)n=n-1;还有线程结束时n=n-1;
// 最后n=0,系统检测为0,才会释放线程
}
顺便提一下Sleep()函数:貌似很简单一个问题,睡觉谁不会呀...却十分体现出CPU分片的问题.
Sleep(400),比如我们的hThread的时间是运行600毫秒,突然运行到300秒,来了个Sleep(400),过了之后,清醒过来,请问现在
hThread还可以运行多少毫秒?是300秒?还是0秒? 应该是0秒...在Sleep睡眠期间,CPU干什么呢?赶快从队列找一个优先级
高线程的来玩玩
b.有异步的地方,肯定需要同步的存在....宏观上是异步,但是执行同一种,同一时间,资源,就需要同步
有很多种具体书籍<<win32多线程设计>>--侯捷译。不知道是谁写的...:-)。这时候什么信号量、互斥对象、事件将会
是你的最爱
void main()
{
HANDLE hMutext=CreateMutex(NULL,true\false,"ccdeath");//true表示调用CreateMutex线程拥有所有权,即main()主线程拥有,其他线称不可以CloseHanle(hMutex),只能
//创建之后都是设为已通知状态. //拥有者释放
}
直接理解:事件为钥匙和要访问的资源为房间,更为简便.
有信号(已通知状态):就是告诉线程,说偶(事件)这边有钱,大家(线程)快来抢钱...
c.类型转换
PVOID& IoctlBuffer (void);ULONG RegWord;
(ULONG)IocltBuffer()=?RegWord;----1.先PVOID===指针+void。先解决void转化
(ULONG *)IocltBuffer()=RegWord;---2.接着解决指针转化
------------------------------------3.转化完之后.再进行一般化处理
|----------------------------------------------------------------|
|int *p;-----------------------------ULONG * IocltBuffer() |
|int i=5;----------------------------ULONG RegWord; |
|*p=i;-------------------------------*IoCltBuffer()=RegWord; |
|----------------------------------------------------------------|
*(ULONG *)IocltBuffer()=RegWord-----4.这才是是正确的.
我们看IocltBuffer()是个指针.
d.类型定义,虽然看似简单.
typedef NTSTATUS (*R)(KIrp I);------5
NTSTATUS wo(Krp I)------------------6
R=&wo;------------------------------7 什么情况下成立,就是5和6参数和返回值要相同.
有时候在DDK编程中出现NTSTATUS **AddDevice(PDRIVER_OBJCET DriverObject,PDEVICE_OBJECT fdo);
DriverEntry()
{ DriverObject->MarjorFunction[IRP_MJ_XX]}=**AddDevice;//我们是怎么判断为什么她的原形是上面那个呢?用VC助手
//go一下,跑到MajorFunction[]就明白。原来用了typedef,从根据根据上面7就知道了,类型与返回值要相同...
规律总结typedef int p;
p i=5;
就是把变量(在int p时候,p为变量)当成类型(typedef int p,p为类型)来用。
5.接下来我们继续看实际例子,从武安河稍微改装了一个,一个是基于DS+main(),另为一个是基于DS+MFC测试程序。
a.我的DS是3.2。好象没有main和MFC框架只有win32sdk。不知道你们是不是...碰到好多人跟偶是一样的....
*.inf:配置文件,怎么安装驱动,提供这个驱动的拥有者的信息之类的等...
*.sys:我们要的驱动....驱动大业,蒸蒸日上;看学学院,蒸蒸日上。
首先点"DDK Build Settings"->Luanch Program.接着启动VC,工具栏就看见DriverStudio工具栏了.点设置,开始...
在设置中,反正没有console测试程序,干脆测试程序就不要集成到驱动程序里面去。把设置中的"集成测试程序"打勾
给去掉...自己在写一个集成测试程序,再集合到驱动程序也一样...
1.文件打开空间(*dsw) ,去到C:\Program Files\Compuware\DriverStudio\DriverWorks\source下重新编译一下,
选择批(最后两个)组建.
Build Environment Variables
BASEDIR=H:\WINDDK\2600
vdw_wdm.lib - 0 error(s), 0 warning(s)
就OK了...
2.然后再编译,靠,还出现问题...不怕,偶已经从win2003 ddk中把需要的文件都拷贝过来了。缺什么,偶们就补什么..
csq.lib
csq.h
ntstrsafe.lib
在附件里,偶会上传的.
3.基本OK了。开始写驱动,接着写驱动程序,接着调试驱动程序,接着安装驱动程序,打开监视器观察是否有错误发生,再
返回来修改驱动程序。好了,一步步来了...
先在DriverEntry(){ DbgPrint("驱动加载了....");} 编译一下,生成*.sys. 用监视器(DS里面的工具Moniter)打开这个
*.sys.接着按go...是不是看到驱动加载了...
122.734 Default CCDeath: CCDeathDriver::DriverEntry++. Compiled at 21:33:07 on Dec 7 2007
122.734 Default CCDeath: 驱动加载了....
122.734 Default CCDeath: CCDeathDriver::DriverEntry--. STATUS 0
122.734 Default CCDeath: CCDeathDriver::Unload++.
122.734 Default CCDeath: CCDeathDriver::Unload--.
Monitor -- end --
高兴吧....
要写一个通信程序...驱动程序和应用程序是两个不同世界的人...想沟通是需要桥梁的....
按照上面方法创建一个驱动程序为CCDeath.沟通的桥梁就是CCDeathInterface.h和CCDeathIoctl.h,自己手动添加...具体
要里面的内容要看书籍才行。具体函数就是DeviceControl()这个东西。
CCDeathIoctl.h://控制命令,请注意存放了如何ruan 冲区的方式是METHOD_BUFFERED\METHOD_IN_DIRECT\METHOD_NEITHER
CCDeathInterface.h//设备的接口,我们可以用的....
从新打开一个工程新建一个consle测试程序.为TestCCDeath;也包含CCDeathInterface.h和CCDeathIoctl.h这两个头文件才
能沟通..."..//CCDeathInterface.h" "..//CCDeathIoctl".
把TestCCDeath放入到CCDeath目录下,接着打开CCDeath工程,选择“工程”->"插入工程到工作空间"。
添加头文件和变量
//添加头文件:
#include "..\\CCDeathInterface.h"
#include "..\\CCDeathIoctl.h"
//添加变量:
GUID CCDeathClassGuid=CCDeathDevice_CLASS_GUID;//要修改下面一个函数哦
在DeviceControl()函数中对3中方式进行处理...
NTSTATUS CCDeathDevice::DeviceControl(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
switch (I.IoctlCode())
{
case READ_DWORD:
status=CCDeath_DWORD_Hander(I);
break;
case READ_STRING:
status=CCDeath_STRING_Hander(I);
break;
case READ_BOOLEAN:
status=CCDeath_BOOLEAN_Hander(I);
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
return status;
}
NTSTATUS CCDeathDevice::CCDeath_DWORD_Hander(KIrp I)
{
....
处理
}
三个处理共同点:
I.information()=sizeof(ULONG);//成功的时候
I.information()=0;//失败的时候
三个处理不同点:
写测试程序:
碰到第一个问题:Cannot open include file: 'devintf.h': No such file or directory
解决方法:在TestCCDeath.dsp加这么一行
# ADD CPP /I "$(DRIVERWORKS)\include"
碰到第二个问题:
OpenByInterface.obj : error LNK2001: unresolved external symbol __imp__SetupDiDestroyDeviceInfoList@4
OpenByInterface.obj : error LNK2001: unresolved external symbol __imp__SetupDiGetClassDevsA@16
OpenByInterface.obj : error LNK2001: unresolved external symbol __imp__SetupDiGetDeviceInterfaceDetailA@24
OpenByInterface.obj : error LNK2001: unresolved external symbol __imp__SetupDiEnumDeviceInterfaces@20
Release/TestCCDeath.exe : fatal error LNK1120: 4 unresolved externals
执行 link.exe 时出错.
TestCCDeath.exe - 1 error(s), 0 warning(s)
解决方法:#pragma comment(lib,"setupapi")
一切OK 了,运行一下测试程序结果。
开始要测试CCDeath驱动程序了:
错误码ERROR opening device: (0) returned from CreateFile
退出测试程序...
Press any key to continue
碰到问题三:上面的运行失败了。
解决办法那是我们还没安装驱动了...
b.安装驱动:有2种方法,个人比较喜欢下面这种...因为简单,所以喜欢....
1.先打开DS中的工具Monitor开始监视
2.打开DS中的工具EZDriverInstaller(快速安装驱动),选择*.inf。在Add New Device,加载*.sys.
OK
3.运行我们的测试程序.
4.观察监视机,再反复调试..softice ... 下次见了...
运行结果:
开始要测试CCDeath驱动程序了:
设备已经被发现,打开句柄成功....
READ_DWORD:0x1e240
Press any key to continue
.
--------------------------------------------------------------------------------
【经验总结】
下一次继续哦.....觉得有帮助...顶顶哦....
Press any key to continue....
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年12月07日 23:06:35
- 标 题: 真正的驱动入门()[附小程序代码]
- 作 者:CCDeath
- 时 间:2007-12-07 23:13
- 附 件:CCDeath4.rar
- 链 接:http://bbs.pediy.com/showthread.php?t=56192