📄 华程电子 - 分类应用(usb开发)软件篇.htm
字号:
用于同步操作的Overlapped结构体指针 <BR>); <BR>IOCTL请求有四种缓冲策略,下面一一介绍。 <BR>1、
输入输出缓冲I/O(METHOD_BUFFERED)
<BR>I/O管理器首先分配一个非分页池,它足够大地存放调用者的输入或输出缓冲区(不管哪个更大)。非分页缓冲区的地址放在IRP的AssociatedIrp.SystemBuffer域中,然后把IOCTL的输入数据拷贝
到这个非份页缓冲区中,并把IRP的UserBuffer域设置成调用者输出缓冲区的用户空间地址。当驱动程序完成IOCTL请求时,I/O管理器将这个非份页缓冲区中的数据拷贝到调用者的输出缓冲区。注意这里同一个非份页池同时用于输入和输出缓冲区,因此驱动程序在向缓冲区写东西之前应该把输入的所有数据读出来。
<BR>2、 直接输入缓冲输出I/O(METHOD_IN_DIRECT)
<BR>I/O管理器首先检查调用者输入缓冲区的可访问性,并在物理内存中将其锁定。然后为该输入缓冲区创建一个MDL,并把指定该MDL的指针存放到IRP的MdlAddress域中。同时,I/O管理器还在非份页池中分配一输出缓冲区,并把这个缓冲区的地址存放在IRP的AssociatedIrp.SystemBuffer域中,并把IRP的UserBuffer域设置成调用者输出缓冲区的用户空间地址。当驱动程序完成IOCTL请求时,I/O管理器将非份页缓冲区中的数据拷贝到调用者的输出缓冲区。<BR>3、
缓冲输入直接输出I/O(METHOD_OUT_DIRECT)
<BR>I/O管理器首先检查调用者输出缓冲区的可访问性,并在物理内存中将其锁定。然后为该输出缓冲区创建一个MDL,并把指定该MDL的指针存放到IRP的MdlAddress域中。同时,I/O管理器还在非份页池中分配一输入缓冲区,并把这个缓冲区的地址存放在IRP的AssociatedIrp.SystemBuffer域中,
同时把调用者用户输入缓冲区中的数据拷贝到系统缓冲区中,并把IRP的 UserBuffer域设置为NULL。 <BR>4、
上面三种方法都不是(METHOD_NEITHER) <BR>I/O管理器把调用者的输入缓冲区的地址放到IRP当前I/O堆栈单元的Parameters.Devi
ceIoControl.TypeInputBuffer域中,把输出缓冲 区的地址存放到IRP的UserBuffer域中。这两个地址都是用户空间地 址。
<BR>从上面的说明可以看出,在执行缓冲I/O时,I/O管理器将在非份页池 中分配内存,如果调用者的缓冲区比较大时,分配的非份页池也将
比较大。非份页池是系统比较宝贵的资源,因此,如果调用者的缓 冲区比较大时,我们一般采用直接I/O的方式(例如磁盘读写请求等),
这样不仅节省系统资源,另一方面由于省去了I/O管理器在系统缓冲 区和调用者缓冲区之间的数据拷贝,也提高了效率,这对存在大量 数据传送的驱动程序尤其明显。
<BR>可以注意到DDK中的Samples下,几乎所有的例程的读写请求都是直 接I/O的,而对于IOCTL请求则是缓冲区I/O的居多。
<BR><BR><FONT color=#ff0000>开始驱动程序设计
</FONT><BR>下面的文字是从Microsoft的DDK帮助中节选出来的,它让我们明 白在开始设计驱动程序应该注意些什么问题,这些都是具有普遍
意义的开发准则。应该支持哪些I/O请求在开始写任何代码之前, 应该首先确定我们的驱动程序应该处理哪些IRP例程。
<BR>如果你在设计一个设备驱动程序,你应该支持和其他相同类型 设备的NT驱动程序相同的IRP_MJ_XXX和IOCTL请求代码。
<BR>如果你是在设计一个中间层NT驱动程序,应该首先确认你下层 驱动程序所管理的设备,因为一个高层的驱动程序必须具有低层
驱动程序绝大多数IRP_MJ_XXX例程入口。高层驱动程序在接到I/O 请求时,在确定自身IRP当前堆栈单元参数有效的前提下
,设置好IRP中下一个低层驱动程序的堆栈单元,然后再调用IoCallDriver 将请求传递给下层驱动程序处理。
<BR>一旦决定好了你的驱动程序应该处理哪些IRP_MJ_XXX,就可以开始 确定驱动程序应该有多少个Dispatch例程。当然也可以考虑把某些
RP_MJ_XXX处理的例程合并为同一例程处理。例如在ChangerDisk和
VDisk里,对IRP_MJ_CREATE和IRP_MJ_CLOSE处理的例程就是同一函数。
对IRP_MJ_READ和IRP_MJ_WRITE处理的例程也是同一个函数。 <BR>应该有多少个Device对象?
<BR>一个驱动程序必须为它所管理的每个可能成为I/O请求的目标的物理和逻辑设备创建一个命名Device对象。一些低层的驱动程序还可能要创建一些不确定数目的Device对象。例如一个硬盘驱动程序必须为每一个物理硬盘创建一个Device对象,同时还必须为每个物理磁盘上的每个逻辑分区创建一个Device对象。<BR>一个高层驱动驱动程序必须为它所代表的虚拟设备创建一个Device
对象,这样更高层的驱动程序才能连接它们的Device对象到这个驱动程序的Device对象。另外,一个高层驱动程序通常为它低层驱动
程序所创建的Device对象创建一系列的虚拟或逻辑Device对象。 <BR>尽管你可以分阶段来设计你的驱动程序,因此一个处在开发阶段的
驱动程序不必一开始就创建出所有它将要处理的所有Device对象。
但从一开始就确定好你最终要创建的所有Device对象将有助于设计者所要解决的任何同步问题。另外,确定所要创建的Device对象还有助于你定义Device对象的Device
Extension的内容和数据结构。 <BR>开始驱动程序开发 <BR>驱动程序的开发是一个从粗到细逐步求精的过程。NT DDK的src\
目录下有一个庞大的样板代码,几乎覆盖了所有类型的设备驱动程序、高层驱动程序和过滤器驱动程序。在开始开发你的驱动程序之前,你应该在这个样板库下面寻找是否有和你所要开发的类似类型的例程。例如我们所开发的驱动程序,虽然DDK对USB描述得不是很详细,我们还是可以在src\storage\class目录发现很多和USB设备有关的驱动程序。下面我们来看开发驱动程序的基本步骤。
<BR>最简的驱动程序框架 <BR>1、 写一个DriverEntry例程,在里面调用IoCreateDevice创建 一个Device对象。 <BR>2、
写一个处理IRP_MJ_CREATE请求的Dispatch例程的基本框架 (参见DDK Kernel-Mode Drivers
4.4.3描述的一个DispatchCreate 例程所要完成的最基本工作。当然写了DispatchCreate例程后,
要在DriverEntry例程为IRP_MJ_CREATE初始化例程入口)。如果驱动程序创建了多于一个Device对象,则必须为IRP_MJ_CLOSE
请求写一个例程,该例程通常情况下可以和DispatchCreate共用一个例程,参见参见DDK Kernel-Mode Drivers 4.4.3。
<BR>3、 编译连接你的驱动程序。 <BR>用下面的方法来测试你的驱动程序。 <BR>首先按上面介绍的方法安装好驱动程序。
<BR>其次我们还得为NT逻辑设备名称和目标Device对象名称之间建立 起符号连接,我们在前面已经知道Device对象名称对WIN32用户模式
是不可见的,是不能直接通过API来访问的,WIN 32 API只能访问NT 逻辑设备名称。我们可以通过修改注册表来建立这两种名称之间的符
号连接。运行REGEDT32.EXE在\HKEY_LOCAL_MACHINE\ System\ CurrentControlSet\Control\
Session Manager\ DOS Devices下建立起符号连接(这种符号连接也可以在驱动程序里调用函数
IoCreateSymbolicLink来创建)。<BR>重新启动系统。 <BR>编写一个简单的测试程序调用WIN32API
CreateFile函数以刚才你命名的NT逻辑设备名打开这个设备。如果打开成功,那么你也就成功地写出了一个最简单的驱动程序了。 <BR>支持更多的设备I/O请求
<BR>例如你的驱动程序可能需要对IRP_MJ_READ请求做出响应(完成后可用WIN32 API
ReadFile函数进行测试)。如果你的驱动程序需要能够手工卸载,那么还必须对IRP_MJ_CLOSE做出响应。为你所需要处理IRP_MJ_XXX写好处理例程,并在DriverEntry里面初始化好这些例
程入口。 <BR>一个低层的驱动程序可能需要最起码一个StartIo,ISR和DpcForIsr
例程,可能需要一个SynchCritSection例程,如果设备使用了DMA, 那么可能还需要一个AdapterControl例程。关于这些例程,请参考
DDK相应文档。 <BR>对于高层驱动程序可能需要一个或多个IoCompletion例程,最起码
完成检查I/O状态块然后调用IoCompleteRequest的工作。 如果需要,还要对Device Extension数据结构和内容做些修改。
<BR></FONT></P><FONT face=宋体>
<HR SIZE=1>
</FONT>
<P><FONT
face=宋体>驱动程序的书写过程的确是很烦人的,从你开始理解结构开始,你就像掉在一个泥潭里一样,无论你如何出拳,发觉总是稀泥一堆。即使你是计算机高手,可以写三千行源代码没犯一个错,一次写完,一次就编译通过(我的一个“同事”在面试的时候对我们老板说的,我想他说的对,他没犯一个错,而是犯了三十万零一个半错,不过,由不的你不信,俺朋友老板就信世间有这类高手,并供为上宾),你还得了解一些基础的硬件知识,你还要了解你的驱动程序的设备的种类,设备的硬件结构,一些特殊的寄存器,或许一些更基础的汇编程序你也的去跑一遍。还的去看什么微微有点软出的什么鸟DDK(这玩意是最重要的),我看像敌敌畏(啊啊,给我一杯敌敌畏,让我不用写程序........哈哈,我的水平直逼牛得滑了,好耍!好耍!)。然后你开始写了一大堆你自认为不比“葵花宝典”差的驱动程序,嘿嘿,你发觉整个程序就是编译不过去,就好像你花十块零五毛RMB买了本“葵花宝典”,终于下定决心按照书的首页要求的引刀什么的,可是你发觉费了九马二骡之力引完了刀,神功依旧未成,点解!你又得去学什么程序调试,去Debug,俺们称其为捉虫,NN的,TMD,虫没有捉到,脑袋可肿的大大的。什么SOFTICE,WINDBG之类,尽是一些系统杀手的角色,一不小心改错了一个内存地址,哼,我CRASH你的机器,你只好又装机,又调试,又死翘翘,你不见密西西比河不死心,又重来一遍,如此三番,惹得你无名火起,起身饮茶,又见隔壁部门的老板正和小蜜在讨论周末去哪里加班工作,不由的气不打一处出,大吼一声“呔,来将何人!洒家张翼德在此!”..........哎,人在老板下,哪能不干活,只有硬头再上.............无数次的失败,无数次的徒劳之后,终于让你的机器跑的欢极了,你不由的小哼一句“对面的小蜜看过来,这里的男孩很能干!”<BR>驱动程序真的得看个人造化,若你有张无忌般奇遇,有韦小宝般艳福,有段舆般韧劲,(对了,还要有东方不败般的勇气)还有什么做不了的。哈哈!</FONT></P>
<HR>
说明:上面文章系转贴,原作者网站为:<A
href="http://embuffalo.myetang.com/">http://embuffalo.myetang.com/<A
href="http://embuffalo.myetang.com/"><FONT
face="宋体, MS Song">/</A></FONT></A></FONT>
<SCRIPT language=javascript>
<!--Power by edxsky.com
article_view2(93,'USB开发步骤之软件篇',2375,'jessica',92,'USB开发步骤之标准篇',94,'USB开发步骤之硬件篇');
article_bar_top('文章分类',0);
sort_type('article_list.asp?',0,0);
article_bar_end('',0);
article_bar_top('文章评论',0);
-->
</SCRIPT>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=bg_tds height=20> → <A
onclick="document.all.review_word.style.display=document.all.review_word.style.display=='none'?'':'none';return false;"
href="javsscript:;"><B>评论内容</B> (点击查看)</A> 共<FONT
class=red>0</FONT>条评论,每页显示<FONT class=red>20</FONT>条评论 <A
onclick="javascript:open_win('review.asp?action=list&rsort=art&re_id=93','review_list',500,400,'no');"
href="javascript:;">浏览所有评论</A></TD></TR>
<TR id=review_word>
<TD class=bg_td align=middle>
<TABLE class=table borderColor=#808080 cellSpacing=1 cellPadding=2
border=0>
<TBODY>
<TR class=bg>
<TD class=gray>(没有相关评论)</TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD class=bg_tds height=20> <B>→ <A
onclick="document.all.review_add.style.display=document.all.review_add.style.display=='none'?'':'none';return false;"
href="javsscript:;"><FONT class=red_3>发表我的评论</FONT></A></B></TD></TR>
<TR id=review_add>
<TD align=middle>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR align=middle>
<TD width="75%">
<TABLE cellSpacing=0 cellPadding=2 border=0>
<FORM name=review_frm onsubmit=javascript:frm_submitonce(this);
action=review.asp?rsort=art&re_id=93&ruser=jessica&rurl=article%5Fview%2Easp%3Fid%3D93
method=post>
<TBODY>
<TR>
<TD>您的姓名:</TD>
<TD><INPUT maxLength=20 size=15 value=xiaobing
name=rusername> 您的Email:<INPUT maxLength=50 size=24
name=remail></TD></TR>
<TR vAlign=top>
<TD class=htd>评论内容:<BR>250字内</TD>
<TD><TEXTAREA name=rword rows=4 cols=55></TEXTAREA></TD></TR>
<TR>
<TD>发表评论:</TD>
<TD><INPUT type=submit value=点击发表评论> <INPUT type=reset value=重新填写> 发表评论须知 →</TD></TR></FORM></TBODY></TABLE></TD>
<TD width="25%">
<TABLE cellSpacing=0 cellPadding=2 width="100%" border=0>
<TBODY>
<TR>
<TD class=gray>
<LI>尊重网上道德,遵守《全国人大常委会关于维护互联网安全的决定》及中华人民共和国其他各项有关法律法;</LI></TD></TR>
<TR>
<TD class=gray>
<LI>本站有权保留或删除您发表的任何评论内容;</LI></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD height=2></TD></TR></TBODY></TABLE>
<SCRIPT language=javascript>
<!--Power by edxsky.com
article_bar_end('',0);
num_rs=13;
pro_edition='21ele_V7.01(ACCESS)';
exec_tim='171.875';
web_right();
web_end(0);
-->
</SCRIPT>
<SCRIPT language=javascript src=""></SCRIPT>
<SCRIPT language=javascript
src="华程电子 - 分类应用(usb开发)软件篇.files/edxsky_lmenu.js"></SCRIPT>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -