﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-只有有耐心圆满完成简单工作的人，才能够轻而易举地完成困难的事。-随笔分类-性能监测</title><link>http://www.cppblog.com/leetaolion/category/4831.html</link><description>Only those who have the patience to do simple things perfectly ever acquire the skill to do difficult things easily. </description><language>zh-cn</language><lastBuildDate>Wed, 21 May 2008 00:12:03 GMT</lastBuildDate><pubDate>Wed, 21 May 2008 00:12:03 GMT</pubDate><ttl>60</ttl><item><title>读懂常见IRP:IRP_MJ_CLEANUP\IRP_MJ_CLOSE\IRP_MJ_CREATE</title><link>http://www.cppblog.com/leetaolion/archive/2007/12/22/39284.html</link><dc:creator>创建更好的解决方案</dc:creator><author>创建更好的解决方案</author><pubDate>Sat, 22 Dec 2007 08:36:00 GMT</pubDate><guid>http://www.cppblog.com/leetaolion/archive/2007/12/22/39284.html</guid><wfw:comment>http://www.cppblog.com/leetaolion/comments/39284.html</wfw:comment><comments>http://www.cppblog.com/leetaolion/archive/2007/12/22/39284.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/leetaolion/comments/commentRss/39284.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/leetaolion/services/trackbacks/39284.html</trackback:ping><description><![CDATA[<p><font style="BACKGROUND-COLOR: #cce8cf">根据MSDN翻译的，网上许多兄弟问此类的问题，解答很少。希望本文能有所帮助。</font></p>
<p>IRP_MJ_CLEANUP</p>
<p>保持进程定义上下文信息的驱动器，必须在DispatchCleanup中包含cleanup请求。</p>
<p>何时发送：<br>收到IRP_MJ_CLEANUP意味着请求的目标设备与目标文件的句柄相关（也可能因为io请求后没有释放）</p>
<p>入参：<br>无</p>
<p>出参：<br>无</p>
<p>操作：<br>该IRP在关闭 file&nbsp; object 句柄的进程上下文中发送。因此，驱动器应该释放进程上下文中所指定的资源，比如之前驱动器锁定或映射的user memory等。<br>如果驱动器的 device objects 状态是exclusive，则该device是独占性的，一次只能为一个线程服务。驱动器必须结束当前目标 device object 队列中的所有IRP，并设置其I/O status block为STATUS_CANCELLED。<br>另外，驱动器只是需要取消并结束与待释放的file object句柄相关的IRP队列成员。（指向file object的指针位于驱动器IRP IO_STACK_LOCATION的FileObject成员中。）取消队列中的IRP后，驱动器结束了clear up IRP操作，并将自身的I/O status block置为STATUS_SUCCESS。<br>//------------------------------------------------------------------------------------------<br>IRP_MJ_CLOSE</p>
<p>驱动器必须在DispatchClose中包含关闭请求和驱动器的可能发生的异常，因为该驱动器只能通过关闭系统来卸载设备，保持了系统分页文件的的磁盘驱动器就属于这类驱动器。具有该类特性驱动器支持动态卸载。</p>
<p>何时发送：<br>收到IRP_MJ_CLOSE请求意味着与目标device object相关的file object句柄已经关闭或释放。所有的外部I/O请求都已结束或取消。</p>
<p>入参：<br>无</p>
<p>出参：<br>无</p>
<p>操作：<br>很少有设备会设置IRP的status block为STATUS_SUCCESS结束关闭请求。驱动器如何处理关闭请求取决于其设计。通常，驱动器在收到IRP_MJ_CREATE后会undo自己的操作结果。device object为exclusive的驱动器，比如串行驱动器，在收到该请求后也可能会reset硬件。<br>IRP_MJ_CLOSE不是在关闭了file object句柄的进程上下文中发送的。如果驱动器必须释放进程指定的资源，比如驱动器之前锁定或映射的user memeory等，就会对IRP_MJ_CLEANUP请求做同样的响应。<br>//------------------------------------------------------------------------------------------<br>IRP_MJ_CREATE</p>
<p>kernel-mode驱动器必须在DispatchCreate或DispatchCreateClose中提出创建请求。</p>
<p>何时发送：<br>收到该请求意味着user-mode保护的子系统（可能代表的是某个应用程序），请求一个file object句柄，该局并代表特定的目标device object，或者是较高级别的驱动器正在连接器device object到目标device object。</p>
<p>入参：<br>无</p>
<p>出参：<br>无</p>
<p>操作：<br>与IRP_MJ_CLOSE类似，对IRP_MJ_CREATE的相应取决与驱动器的设计，很少有驱动器会设置IRP的I/O status block为STATUS_SUCCESS。带有pageable-image单元的驱动器，像系统串行驱动器，会通过映射自身的page-out代码，来为那些尝试打开设备进行I/O操作的user-mode线程提供资源。</p>
<p>//------------------------------------------------------------------------------------------<br>IRP_MJ_DIRECTORY_CONTROL</p>
<p>何时发送：<br>IRP_MJ_DIRECTORY_CONTROL请求是由I/O管理器和其他操作系统组件（比如kernel-mode驱动器）发送的。当user-mode程序调用ReadDirectoryChangesW、FindNextVolumeMountPoint或者kernal-mode componenet调用ZwQueryDirectoryFile时，会发送该请求。</p>
<p>操作：文件系统驱动器<br>文件系统驱动器通过检查监控程序code来判断判断执行哪一个目录控制操作。有效的监控程序codes:<br>IRP_MN_NOTIFY_CHANGE_DIRECTORY<br>请求告知目录变更。通常文件系统驱动器会将此IRP放到私有的队列中，而不是立即进行满足该请求。 当目录发生变更时，文件系统驱动器执行通知目录变更操作，出队，结束该IRP。<br>IRP_MN_QUERY_DIRECTORY<br>目录查询请求。消息类型因文件系统而异，通常包括以下几种：<br>FileBothDirectoryInformation<br>FileDirectoryInformation<br>FileFullDirectoryInformation<br>FileIdBothDirectoryInformation<br>FileIdFullDirectoryInformation<br>FileNamesInformation<br>FileObjectIdInformation<br>FileReparsePointInformation</p>
<p>注意：FileQuotaInformation类已不再使用，用IRP_MJ_QUERY_QUOTA代替。<br>执行之后，结束IRP。</p>
<p>操作：文件系统过滤驱动器<br>过滤驱动器将该IRP向栈上的下一层驱动器传递。<br>//------------------------------------------------------------------------------------------<br>IRP_MJ_QUERY_INFORMATION</p>
<p>何时发送：<br>IRP_MJ_QUERY_INFORMATION请求的发送和IRP_MJ_DIRECTORY_CONTROL类似，是由I/O管理器和其他操作系统组件（比如kernel-mode驱动器）发送的。调用GetFileInformationByHandle或ZwQueryInformationFile时发送。</p>
<p>操作：文件系统驱动器<br>文件系统驱动器提取file object信息并进行解析，由此判断用户是打开一个文件还是打开一个目录，这样，驱动器处理查询并结束IRP。如果不能对信息进行提取解析，驱动器结束IRP，不处理查询。<br>可供查询的文件和目录信息因文件系统而异，通常包括如下几种：<br>FileAllInformation<br>FileAttributeTagInformation<br>FileBasicInformation<br>FileCompressionInformation<br>FileEaInformation<br>FileInternalInformation<br>FileNameInformation<br>FileNetworkOpenInformation<br>FilePositionInformation<br>FileStandardInformation<br>FileStreamInformation<br>ZwQueryInformationFile支持FileAccessInformation, FileAlignmentInformation, 和 FileModeInformation 类型，而无需向文件系统发送IRP_MJ_QUERY_INFORMATION请求，因为他们与文件系统无关。</p>
<p>操作：文件系统过滤驱动器<br>过滤驱动器将该IRP向栈上的下一层驱动器传递。<br>//------------------------------------------------------------------------------------------<br>IRP_MJ_QUERY_VOLUME_INFORMATION</p>
<p>何时发送：<br>IRP_MJ_QUERY_VOLUME_INFORMATION请求由I/O管理器发送。当user-mode程序调用GetDiskFreeSpace或GetFileType时会发送该请求。</p>
<p>操作：文件系统驱动器<br>文件系统驱动器通过对file object进行提取和解码，判断目标device object是不是该文件系统的control device object。如果是，并且请求的是打开volume（或者打开volume上的object），文件系统驱动器会处理请求并结束IRP。如果不是，文件系统驱动器查询失败，结束IRP。<br>可供查询的volume信息类型因文件系统而异，通常有如下几种类型：<br>FileFsAttributeInformation<br>FileFsDeviceInformation<br>FileFsSizeInformation<br>FileFsVolumeInformation</p>
<p>操作：文件系统过滤驱动器<br>过滤驱动器将该IRP向栈上的下一层驱动器传递。<br>//------------------------------------------------------------------------------------------<br>IRP_MJ_READ</p>
<p>向系统传递数据的驱动器必须在DispatchRead或DispatchReadWrite中包含read请求，在此类驱动器上分层的higher-level驱动器也必须这样做。</p>
<p>何时发送：<br>在完成create请求的之后的时间域内发送。<br>可能由包含file object句柄（代表请求过从从该device传递数据的目标device object）的user-mode程序或win32组件发送。也可能由创建和设置read IRP的higher-level驱动器发送。</p>
<p>入参：<br>IRP中的驱动器I/O stack位置指示Parameters.Read.Length.传送多少byte数据。<br>有些驱动器通过Parameters.Read.Key对在device queue或驱动器管理的IRP内部队列中对read请求进行排序。有的驱动器通过Parameters.Read.ByteOffset（指示传送操作的offset）进行排序。</p>
<p>出参：<br>根据驱动器对device object Flag的是DO_BUFFERED_IO还是DO_DIRECT_IO，采用不同的方法传递数据：<br>The buffer at Irp-&gt;AssociatedIrp.SystemBuffer if the driver uses buffered I/O <br>The buffer described by the MDL at Irp-&gt;MdlAddress if the underlying device driver uses direct I/O (DMA or PIO) </p>
<p>操作：<br>接收到read请求之后，higher-level驱动器会通过为next-lower驱动器设置IRP中的I/O stack位置，或者为lower驱动器创建并设置附加的IRP。可以调用IoSetCompletionRoutine设置IoCompletion（在IRP输入中是可选的，但在driver-created IRP是必须的）。<br>接收到该请求之后，驱动器将器device传送给系统memory。结束IRP的过程中，驱动器将设置I/O stack block为传递的byte数量。<br>&nbsp;<br>//------------------------------------------------------------------------------------------<br>IRP_MJ_SET_INFORMATION</p>
<p>何时发送：<br>IRP_MJ_SET_INFORMATION请求的发送和IRP_MJ_QUERY_INFORMATION、IRP_MJ_DIRECTORY_CONTROL类似，是由I/O管理器和其他操作系统组件（比如kernel-mode驱动器）发送的。调用SetEndOfFile或ZwSetInformationFile时发送。</p>
<p>操作：文件系统驱动器<br>文件系统驱动器提取file object信息并进行解析，由此判断用户是打开一个文件还是打开一个目录，这样，驱动器处理查询并结束IRP。<br>可供设置的文件、目录属性信息如下：<br>FileBasicInformation<br>FileDispositionInformation<br>FileLinkInformation (for file systems that allow cycles to be created in the directory hierarchy)<br>FilePositionInformation<br>FileRenameInformation<br>文件专有属性：<br>FileAllocationInformation<br>FileEndOfFileInformation<br>FileLinkInformation (for file systems, such as NTFS, that do not allow cycles to be created in the directory hierarchy)<br>FileValidDataLengthInformation</p>
<p>操作：文件系统过滤驱动器<br>过滤驱动器将该IRP向栈上的下一层驱动器传递。<br>//------------------------------------------------------------------------------------------<br>IRP_MJ_SET_INFORMATION*<br>IRP_MJ_SET_INFORMATION (Serial)</p>
<p>何时发送：<br>client通过set information请求改变串行设备上打开的文件结尾位置时发送。</p>
<p>//------------------------------------------------------------------------------------------<br>IRP_MJ_WRITE</p>
<p>向系统传递数据的驱动器必须在DispatchWrite或DispatchReadWrite中包含write请求，在此类驱动器上分层的higher-level驱动器也必须这样做。</p>
<p>何时发送：<br>成功结束creat请求的时间域内。<br>可能由包含file object句柄（代表请求过从从该device传递数据的目标device object）的user-mode程序或win32组件发送。也可能由创建和设置write IRP的higher-level驱动器发送。</p>
<p>入参：<br>IRP中的驱动器I/O stack位置指示Parameters.Write.Length.传送多少byte数据。<br>有些驱动器通过Parameters.Write.Key对在device queue或驱动器管理的IRP内部队列中对write请求进行排序。有的驱动器通过Parameters.write.ByteOffset（指示传送操作的offset）进行排序。<br>根据驱动器对device object Flag的是DO_BUFFERED_IO还是DO_DIRECT_IO，采用不同的方法传递数据：<br>The buffer at Irp-&gt;AssociatedIrp.SystemBuffer, if the driver uses buffered I/O <br>The buffer described by the MDL at Irp-&gt;MdlAddress, if the underlying device driver uses direct I/O (DMA or PIO) </p>
<p>出参：<br>无</p>
<p>操作：<br>接收到write请求之后，higher-level驱动器会通过为next-lower驱动器设置IRP中的I/O stack位置，或者为lower驱动器创建并设置附加的IRP。可以调用IoSetCompletionRoutine设置IoCompletion（在IRP输入中是可选的，但在driver-created IRP是必须的）。之后，驱动器通过IoCallDriver传递请求给next-lower驱动器。<br>接收到该请求之后，驱动器将数据从系统memory传递到自身的device。结束IRP的过程中，驱动器将设置I/O stack block为传递的byte数量。 <br>//------------------------------------------------------------------------------------------<br>IRP_MJ_WRITE*<br>分段写入，提供Offset，每次写入65536字节。<br></p>
<img src ="http://www.cppblog.com/leetaolion/aggbug/39284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/leetaolion/" target="_blank">创建更好的解决方案</a> 2007-12-22 16:36 <a href="http://www.cppblog.com/leetaolion/archive/2007/12/22/39284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>