从零开始学驱动到驱动版helloworldWord下载.docx
- 文档编号:16545630
- 上传时间:2022-11-24
- 格式:DOCX
- 页数:20
- 大小:483.15KB
从零开始学驱动到驱动版helloworldWord下载.docx
《从零开始学驱动到驱动版helloworldWord下载.docx》由会员分享,可在线阅读,更多相关《从零开始学驱动到驱动版helloworldWord下载.docx(20页珍藏版)》请在冰豆网上搜索。
其实在系统地读老马的译本之前,我也零零散散的看了些东西,网上查找了不少入门上手的东西,包括楚狂人的文件过滤驱动教程,这篇东西还真是个好东西,虽说不能算是入门级的教程,但我读起来还是颇有兴致,并且障碍不是很大,当然里面也有不少不甚明白的东西,但基本不影响对框架的理解。
之后,开始读老马的译本,差不多花了一个月,算是囫囵过了一遍。
其间还不敢上手写例程,准备读完以后,再细读一遍,把所有的有条件看到效果的例程录入一遍(需要开发板的就先放放)。
笨人就只有笨招,不过这方法对于我来说效果还不错,以前核心编程那本就是这么来着,代码写一遍和读一遍还是不同的。
言归正题吧!
首先得开始搭建环境
操作系统为WindowsXPSP2,接下来你得装个VisualStudio6.0吧,外加上个SP5,当然你可以说VC6只是个编辑器,也不用非在VC的集成环境中编译驱动,是!
没问题,但你总得干点别的活吧,公司里写不完的应用呀,我们同事在LINUX下的代码都在VC6中来写,然后再通过WinSCP传到LINUX下呢。
接下来装什么呢,我又装了个VS.NET2003和MSDN.NET2003,这样SDK2003有了,呵呵,主要是MSDN的内容比较全,DDK的内容也有了,VS6的MSDN就没必要了。
接下来就是安装DDK了,网上找了个WINXPDDK,有134M,不记得在哪找到的了,好像还费了一番周折,WIN2000DDK容易找到些。
安装后,生成的开始菜单如下:
其实现在就可以开始干活了,但还不忙!
驱动程序得有个调试环境吧,驱动的调试总不能在VC6里呀,他们说得用WINDBG或者SOFTICE才能调试内核层面的代码,但SOFTICE在单机上就能调,而WINDBG还得准备两台机器,没那么多银子,那就SOFTICE了。
上网找去!
东转西转的,忍不住还是先看了下说姚明和李宇春有夫妻相的一个链接,找到了看雪学院(Studio3.2的玩意呢,早就听说有这么东西了,说是只要NEXT、NEXT,再NEXT就能生成驱动了,那就都给下了吧。
先解包DriverStudio压缩文件,安装,注意:
这个DriverStudio的安装包还包括SOFTICE的安装,还是不要在DriverStudio里安装SOFTICE吧(有选项可以取消SOFTICE的安装),好像安装后的SOFTICE中,SYMBOLLOADER有问题,SYMBOLLOADER都有问题,那还怎么调试呢。
装完DriverStudio后,开始安装SOFTICE,应该很顺利的。
如果你愿意,可以在Initializationstring设置中添加“FAULTSoff;
SETMAXIMIZEon;
SETFONT3;
CLS;
X;
”(注意没有引号),这样可使得SOFTICE窗口看起来舒服一点,当然你不加,也没有问题。
DriverStudio安装以后,会在VISUALC++的集成环境中添加工具条
和菜单项
。
关于DriverStudio的配置有不少内容,包括DDK的路径配置,目标操作系统等等,当然其中有些是DDK本身的配置,还有一点就是DriverStudio本身的LIB需要根据机器上安装的DDK重新编译一次才行。
由此也可以看出DriverStudio本身的LIB是对DDK的封装,类似于MFC对SDK的封装。
我自己尝试着用DriverStudio创建了一个最基本的驱动程序,打开一开,没头没尾的,就象最初看MFC的代码一样,没有了WinMain或main,有一些莫名的结构定义,整个代码没有了清晰的流程,一块一块的,似乎都不搭界,但其实在MFC内部将各个部分串接了起来,可是你最初怎么可能弄得清楚呢,如果不是侯杰的那本深入浅出MFC,光是靠查看MSDN的帮助,天知道怎么回事呀。
即便是有那本难得的好书,又下了多少功夫才算明白了呢!
我看还是算了,直接用DDK吧,至少你自己能把握的东西更多一些。
抛开DriverStudio的NEXT吧!
但是DriverStudio里的工具还是可以用的:
DriverMonitor和SymbolicLinkViewer等工具还是可以用的,虽然也有别的小工具(比如DevView或者WinObj)可以替代,在后面我会用到这两个工具软件。
关于环境的搭建就写这么多了,其中具体的安装可以上网查找详细的信息。
接下来该写一个驱动程序的”HelloWorld!
”了,主要的目的是为了理顺产生一个驱动程序的通常模式,打通从编辑代码、编译连接、安装驱动、启动驱动、测试调用驱动、调试驱动代码、查看设备及驱动状态,最后到停止驱动整个过程的通道。
在这里我不打算分析具体代码,作为一个HELLOWORLD例程,应该说所有的代码都不难理解,本文的主要目的只是想记录我自己创建调试一个最简单的但是名副其实的驱动程序的完整过程。
如果你现在觉得其中的代码还有困难,那就再回个头来看看IRP、IO_STACK_LOCATION、DriverEntry、MajorFunction、DEVICE_OBJECT、CreateFile、DeviceIoControl等等概念吧。
在这里我引用的代码是网上的一篇文章,就是介绍驱动版的“HelloWorld”的。
(zhangjie0072的专栏
首先将代码录入(我先打印了网页,然后手工敲入所有代码,没有COPY和PASTE,开始阶段这种录入工作对于我来说是一个很好的熟悉过程,即便是重复的代码我也觉得很舒服,嘿嘿,当然,好在代码都不长)。
我还是使用VC6的集成环境来作为编辑器,当然你使用记事本也没问题。
四个文件:
HelloWorld.c,HelloWorld.h,makefile,source.(都在D:
\CurrentWork\DrvWork\HelloWorld目录下),makefile和sources为编译的相关配置文件。
下面列出四个文件的完整代码(再次感谢zhangjie0072!
),不过我都没有录入注释了,sorry。
=============================HelloWorld.h========================================
#ifndef__HELLOWORLD_H__
#define__HELLOWORLD_H__
#include<
ntddk.h>
#defineDEVICE_HELLO_INDEX0x860
#defineSTART_HELLOWORLDCTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)
#defineSTOP_HELLOWORLDCTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+1,METHOD_BUFFERED,FILE_ANY_ACCESS)
#defineNT_DEVICE_NAMEL"
\\Device\\HelloWorld"
#defineDOS_DEVICE_NAMEL"
\\DosDevices\\HelloWorld"
NTSTATUSHelloWorldDispatch(INPDEVICE_OBJECTDeviceObject,INPIRPpIrp);
VOIDHelloWorldUnload(INPDRIVER_OBJECTDriverObject);
#endif
=================================HelloWorld.c=======================================
#ifndef__HELLOWORLD_C__
#define__HELLOWORLD_C__
#defineDEBUGMSG
#include"
HelloWorld.h"
NTSTATUSDriverEntry(INPDRIVER_OBJECTDriverObject,INPUNICODE_STRINGRegistryPath)
{
NTSTATUSntStatus=STATUS_SUCCESS;
PDEVICE_OBJECTIpDeviceObject=NULL;
UNICODE_STRINGDeviceNameString;
UNICODE_STRINGDeviceLinkString;
#ifdefDEBUGMSG
DbgPrint("
hi,StartingDriverEntry()\n"
);
#endif
RtlInitUnicodeString(&
DeviceNameString,NT_DEVICE_NAME);
ntStatus=IoCreateDevice(DriverObject,0,&
DeviceNameString,FILE_DEVICE_UNKNOWN,0,FALSE,&
IpDeviceObject);
if(!
NT_SUCCESS(ntStatus))
{
#ifdefDEBUGMSG
DbgPrint("
hi,ErrorIoCreateDevice()\n"
#endif
gotoError;
}
DeviceLinkString,DOS_DEVICE_NAME);
ntStatus=IoCreateSymbolicLink(&
DeviceLinkString,&
DeviceNameString);
hi,ErrorIoCreateSymbolicLink()\n"
DriverObject->
MajorFunction[IRP_MJ_CREATE]=HelloWorldDispatch;
MajorFunction[IRP_MJ_CLOSE]=HelloWorldDispatch;
MajorFunction[IRP_MJ_DEVICE_CONTROL]=HelloWorldDispatch;
DriverUnload=HelloWorldUnload;
returnntStatus;
Error:
hi,ErrorDriverEntry()\n"
}
NTSTATUSHelloWorldDispatch(INPDEVICE_OBJECTDeviceObject,INPIRPpIrp)
ULONGIoControlCodes=0;
PIO_STACK_LOCATIONIrpStack=NULL;
pIrp->
IoStatus.Status=STATUS_SUCCESS;
IoStatus.Information=0;
hi,StartingHelloWorldDispatch()\n"
IrpStack=IoGetCurrentIrpStackLocation(pIrp);
switch(IrpStack->
MajorFunction)
caseIRP_MJ_CREATE:
hi,IRP_MJ_CREATE\n"
break;
caseIRP_MJ_CLOSE:
hi,IRP_MJ_CLOSE\n"
caseIRP_MJ_DEVICE_CONTROL:
hi,IRP_MJ_DEVICE_CONTROL\n"
IoControlCodes=IrpStack->
Parameters.DeviceIoControl.IoControlCode;
switch(IoControlCodes)
{
caseSTART_HELLOWORLD:
DbgPrint("
hi,Starting\"
HelloWorld\"
\n"
break;
caseSTOP_HELLOWORLD:
hi,Stoping\"
default:
pIrp->
IoStatus.Status=STATUS_INVALID_PARAMETER;
}
default:
ntStatus=pIrp->
IoStatus.Status;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
VOIDHelloWorldUnload(INPDRIVER_OBJECTDriverObject)
PDEVICE_OBJECTDeviceObjectTemp1=NULL;
PDEVICE_OBJECTDeviceObjectTemp2=NULL;
hi,StartingHelloWorldUnload()\n"
IoDeleteSymbolicLink(&
DeviceLinkString);
if(DriverObject)
DeviceObjectTemp1=DriverObject->
DeviceObject;
while(DeviceObjectTemp1)
DeviceObjectTemp2=DeviceObjectTemp1;
DeviceObjectTemp1=DeviceObjectTemp1->
NextDevice;
IoDeleteDevice(DeviceObjectTemp2);
=============================makefile========================================
#
#DONOTEDITTHISFILE!
!
EDIT.\SOURCES.IFYOUWANTTOADDANEWSOURCE
#FILETOTHISCOMPONENT.THISFILEMERELYINDIRECTSTOTHEREALMAKEFILE
#THATISSHAREDBYALLTHEDRIVERCOMPONENTSOFTHEWINDOWSNTDDK
INCLUDE$(NTMAKEENV)\makefile.def
=============================sources========================================
TARGETNAME=HelloWorld
TARGETPATH=.
TARGETTYPE=DRIVER
SOURCES=HelloWorld.c
好了,所有驱动程序端的代码已经全部录入完毕了,实话说,这比看书的时候要愉悦得多,特别是这么简单明晰的代码!
要是所有工作都象这样,嘿嘿,你会感受到幸福吗?
边录入边查看MSDN中某些函数的用法,半个小时吧,基本完成这部分的工作。
下面做什么呢,当然接下来就是编译了。
在VC6中也可以进行编译,你可以在网上查找相关文章。
在这里我使用zhangjie0072文中所说的,使用DDK的build来编译。
如上图所示,点击开始菜单中红圈所表示的命令,进入CMD命令行环境,这个命令执行的是一个批处理文件,查看“WinXPCheckedBuildEnvironment”命令的属性,可以看到对应的快捷方式页中的目标为“C:
\WINDOWS\system32\cmd.exe/kC:
\WINDDK\2600\bin\setenv.batC:
\WINDDK\2600chk”,即执行的是DDK中的setenv.bat文件,正如文件名一样,这个批处理文件就是为了设置编译环境的。
为了能够使得编译生成的驱动程序包含调试信息,所以这里使用Checked方式来编译。
查看setenv.bat,里面有很多环境参数设置,如果你确实知道这些参数的含义,你不妨修改它们,但我现在还不敢动。
进入命令行后,进入HelloWorld.c所在的目录,然后键入build开始编译(见下图)。
之后会出现什么呢,天知道。
我第一次编译的时候,一下提示出现一百多个error,我……KAO!
我第一反应就是DDK的设置有问题了,嘿嘿!
虽然是命令行的编译方式,但DDK还是提供了足够的错误提示信息,仔细查看,发现是头文件中少了一空格,使得宏无法被识别,造成连锁反应,看来DDK的设置没有问题,还是自己代码的问题。
见下图。
上面的图只是我有意修改了现在的头文件产生的错误。
开始时候还真有一百多个error,查看给出错误提示信息,一个一个地解决,多数还都是录入时候的错误。
所有问题都PASS了,就是下面这个样子了。
看到红圈中的部分了吗,在D:
\CurrentWork\DrvWork\HelloWorld\i386下生成了helloworld.sys。
有点爽!
第一个驱动程序总算下地了!
接下来该做什么了呢,sys文件有了,我却开始有点茫然了,平时做一个用户模块下的应用程序,编译完了,生成exe文件也好,生成dll文件也好,接下来当然就是运行测试了,可。
驱动程序怎么启动运行呢。
作为真正的硬件,系统Pnp管理器会自己创建PDO,然后查找安装与该PDO相关的驱动程序(包括上层的功能驱动和各种过滤驱动),或者提示用户指定驱动程序的位置然后安装。
可。
这个HelloWorld算怎么回事呢?
还有一个问题,是先有了驱动程序还是先有DEVICE_OBJECT呢,DEVICE_OBJECT不是在驱动程序的AddDevice或者就直接在DriverEntry中创建的吗?
先琢磨琢磨!
这是个关键的问题。
嘿!
驱动程序是鸡,DEVICE_OBJECT是蛋!
PDO是由总线驱动程序创建的,再由PDO相关的功能驱动和过滤驱动创建各自的FDO和FIDO。
应该是这样的吧!
好了,我们开始运行吧,先不管注册表和INF什么的,先手工启动驱动程序再说,他们不是说驱动程序就可以看作一服务吗?
找一找,查一查!
DriverStudio的工具软件包里就有一个工具可以作为启停驱动来用呀。
是的,就是我前面提到过的DriverMonitor。
打开DriverMonitor,File菜单
先“OpenDriver”,找到HelloWorld.sys的位置,然后顺序点击“StartDriver”“StopDriver”“RemoveServiceEntry”,你将看到下面对应的显示。
你确实看到了你在驱动程序中的调试输出"
hi,StartingDriverEntry()"
和"
hi,StartingHelloWorldUnload()"
了,说明你的驱动程序确实启
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 从零开始 驱动 helloworld