XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
阅读:3012回复:9

Windows文件系统过滤驱动开发教程(7)

楼主#
更多 发布于:2004-10-27 18:50
Windows文件系统过滤驱动开发教程

7.IRP完成函数,中断级,如何超越中断级别的限制

先讨论一下Volumne设备是如何得到的.首先看以下几个函数:

// ------------------wdf.h 中的内容 -------------------------
typedef VPB wd_vpb;
_inline wd_vpb * wd_dev_vbp(wd_dev *dev)
{
return dev->Vpb;
}

_inline wd_dev * wd_vbp_dev(wd_vpb *vpb)
{
return vpb->DeviceObject;
}


VPB是Volume parameter block.一个数据结构.它的主要作用是把实际存储媒介设备对象和文件系统上的卷设备对象联系起来.

wd_dev_vbp可以让你从一个Storage Device Object得到一个VPB,而wd_vbp_dev这个函数可以得到这个VPB所对应的Volmue设备.

现在首先要得到Storage Device Object.实际上这个东西保存在当前IO_STACK_LOCATION中.

// ------------------wdf.h 中的内容 -----------------------
_inline wd_dev *wd_irpsp_mount_storage(wd_io_stack *irpsp)
{
return irpsp->Parameters.MountVolume.Vpb->RealDevice;
};

那么,从irp出发,我最终可以通过以下的方式得到Volumue设备:

wd_irpsp *irpsp = wd_cur_io_stack(irp);
wd_dev *storage_dev = wd_irpsp_mount_storage(irp);
wd_vpb *vpb = wd_dev_vbp(storage_dev);
wd_dev *volume_dev = wd_vbp_dev(vpb);

不过实际情况并不这么简单.这里的IRP是一个MOUNT请求.而volume设备对象实际上是这个请求完成之后的返回结果.因此,在这个请求还没有完成之前,我们就试图去获得Volume设备对象,当然是竹篮打水一场空了.

这里,你可以直接拷贝当前IO_STACK_LOCATION,然后向下发送请求,但在此之前,要先给irp分配一个完成函数.irp一旦完成,你的完成函数将被调用.这样的话,你可以在完成函数中得到Volume设备,并实施你的绑定过程.

这里要讨论一下中断级别的问题.常常碰到人问某函数只能在Passive Level调用是什么意思.总之我们的任何代码执行的时候,总是处在某个当前的中断级之中.某些系统调用只能在低级别中断级中执行.请注意,如果一个调用可以在高处运行,那么它能在低处运行,反过来则不行.

我们需要知道的只是我们关心Passive Level和Dispatch Level.而且Dispatch Level的中断级较高.一般ddk上都会标明,如果注明irq level>=dispatch,那么你就不能在passive level的代码中调用它们了.

那么你如何判断当前的代码在哪个中断级别中呢?我一般是这么判断的:如果你的代码执行是由于应用程序(或者说上层)的调用而引发的,那么应该在Passive Level.如果你的代码执行是由于下层硬件而引发的,那么则可能在dispatch level.

希望不要机械的理解我的话!以上只是极为粗略的便于记忆的理解方法.实际的应用应该是这样的:所有的dispatch functions由于是上层发来的irp而导致的调用,所以应该都是Passive Level,在其中你可以调用绝大多数系统调用.而如网卡的OnReceive,硬盘读写完毕,返回而导致的完成函数,都有可能在Dispatch级.注意都是有可能,而不是绝对是.但是一旦有可能,我们就应该按就是考虑.

好,现在我们发现,我们已经注册了完成函数,并且这个函数执行中可能是dispatch level.

现在面临的问题是,我们已经决定在完成函数中调用 IoAttachDeviceToDeviceStack来绑定Volume.而DDK说明有:Callers of IoAttachDeviceToDeviceStack must be running at IRQL <= DISPATCH_LEVEL.

实际上前边说过有IoAttachDeviceToDeviceStackSafe,这个调用可以在Dispatch level进行.无奈这个调用仅仅出现在Xp以上的系统中.

超越中断级别的限制有几种方法.第一种是自己生成一个系统线程来完成此事.系统线程将保证在Passive Level中运行.另一种方法就是把自己的任务插入Windows工作者线程,这会使你的任务迟早得到执行.如果你的任务比较小,可以实行第二种方法.对系统来说比较省事,对程序员来说则反正都是麻烦.

我做了以下几个函数专门来插入任务到工作者线程.
//---------------wdf.h 中的内容 ------------------------
typedef WORK_QUEUE_ITEM wd_work_item;
typedef PWORKER_THREAD_ROUTINE wd_work_func;
// 任务的初始化
_inline wd_void wd_work_init(wd_work_item *item,
wd_work_func worker,
wd_void *context)
{
ExInitializeWorkItem(item,worker,context);
}

// 三种任务队列
typedef enum _wd_work_quque_type{
wd_work_crit = CriticalWorkQueue,
wd_work_delay = DelayedWorkQueue,
wd_work_hyper = HyperCriticalWorkQueue
} wd_work_queue_type;

_inline wd_void wd_work_queue(in wd_work_item *item,
 in wd_work_queue_type type)
{
ExQueueWorkItem(item,(WORK_QUEUE_TYPE)type);
}

_inline wd_void wd_work_run(in wd_work_item *item)
{
(item->WorkerRoutine)(item->Parameter);
}

任务是一个数据结构,已经被我重定义为wd_work_item,wd_work_init能初始化它.初始化的时候你只需要填写一个你的任务的函数.同时一个context用来记录上下相关参数.(这是个空指针,你可以只想你任何想要的参数类型).

一般这个任务会自动执行,但是有时我们也想不插入队列,我们自己执行它.那么调用wd_work_run即可.

然后调用wd_work_queque插入工作者队列,之后会被执行.插入类型这里选择wd_work_delay.

希望你没有被这一串东西搞糊涂.现在我会写一个"设置完成函数"的函数.执行后,自动在Passive Level级执行你的完成函数.希望不会把你搞得晕头转向的:).

// 完成例程上下文。好几个fsctl需要注册完成例程。而例程中的工作可能
// 只能在passive level中运行,因此不得不加入一个work_item,把任务塞
// 入工作线程等待完成
typedef struct _my_fsctl_comp_con
{
wd_work_item work;
wd_dev *dev;
wd_irp *irp;
wd_dev *new_dev; // 这个元素仅仅用于mount的时候。因为我
// 们要生成一个新设备来绑定vdo.
} my_fsctl_comp_con;

wd_bool my_fsctl_set_comp(wd_dev *dev,
wd_irp *irp,
wd_dev *new_dev,
wd_irp_comp_func complete,
wd_work_func work_complete)
{
my_fsctl_comp_con *context;
context = (wdff_fsctl_comp_con *)wd_malloc(wd_false,
  sizeof(wdff_fsctl_comp_con));
if(context == NULL)
{
wd_printf0("fsctl set comp: failed to malloc context.\r\n");
return wd_false;
}

// 初始化工作细节
wd_work_init(&context->work,
work_complete,
context);

context->dev = dev;
context->irp = irp;
context->new_dev = new_dev;

// 设置irp完成例程
wd_irp_comp(irp,complete,context);

return wd_true;
}

// 以下函数作为以上complete的参数被使用
wd_stat my_fsctl_comp(in wd_dev *dev,
in wd_irp *irp,
in wd_void *context)
{
wd_printf0("fsctl_comp: come in!!!\r\n");
UNREFERENCED_PARAMETER(dev);
UNREFERENCED_PARAMETER(irp);
// 判断当前中断级
if(wd_get_cur_irql() > wd_irql_passive)
{
wd_printf0("fsctl_comp:into quque!!!\r\n");
// 如果在passive更低的中断级别,必须插入延迟队列中运行
wd_work_queue((wd_work_item *)context,wd_work_delay);
}
else
{
// 否则可以直接执行
wd_printf0("fsctl_comp:run directly!!!\r\n");
wd_work_run((wd_work_item *)context);
}
return wd_stat_more_processing;
}

我想以上的过程应该已经可以理解了!注册了基本的完成历程complete函数(也就是我最后写的函数my_fsctl_comp后),irp执行完毕回调my_fsctl_comp,而我事先已经把已经做好的任务(wd_work_item)写在上下文指针中(context)中.一回调这个函数,我就wd_work_queque插入队列.结果wd_work_item中记录的work_complete函数显然会在Passive level中执行.我们的系统也将保持稳定.

work_complete函数将从context上下文指针中得到足够的参数,来完成对Volume的绑定.

希望你没有被弄昏头:),我们下回再分解.

最新喜欢:

yuanycyuanyc forgetalexforget...
XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
沙发#
发布于:2004-10-27 21:04
如下方法从irpsp得到volume
...
wd_dev *storage_dev = wd_irpsp_mount_storage(irp);
...

有误,应为wd_dev *storage_dev = wd_irpsp_mount_storage(irpsp);

此外wd_io_stack 和wd_irpsp都有出现,这是不应该的,因为它们都是IO_STACK_LOCATION.这两个是一样的。


keddyzhou
驱动牛犊
驱动牛犊
  • 注册日期2004-10-27
  • 最后登录2007-01-22
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-10-27 21:22
。。。。。。还在呐,够兢业的。 :D
cicada
驱动小牛
驱动小牛
  • 注册日期2003-12-09
  • 最后登录2008-07-11
  • 粉丝1
  • 关注0
  • 积分74分
  • 威望15点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-10-28 09:09
顶,继续!
kevin73
驱动牛犊
驱动牛犊
  • 注册日期2004-10-27
  • 最后登录2005-06-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-10-28 20:19
顶,继续收藏,谢谢! :D
kevin73
驱动牛犊
驱动牛犊
  • 注册日期2004-10-27
  • 最后登录2005-06-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-10-29 09:35
今天又新的吗,加油呀!
newkey
驱动小牛
驱动小牛
  • 注册日期2002-10-03
  • 最后登录2013-10-13
  • 粉丝1
  • 关注0
  • 积分45分
  • 威望392点
  • 贡献值1点
  • 好评度90点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-11-01 10:53
我买马

转载一篇ms的


FILE SYSTEM FILTER MANAGER
Filter Driver Development Guide



Summary
This specification includes, but is not limited to, the following topic areas:
&#8226; Description of the new 'File System Filter Manager' architecture and interfaces
&#8226; Aspects of the Windows 'Memory Manager', 'I/O Manager', and 'Cache Manager' interfaces that affect the development of file system filters using the new File System Filter Manager architecture.
Disclaimer
The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.

This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT.

Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.

Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, email address, logo, person, place or event is intended or should be inferred.

? 2004 Microsoft Corporation.  All rights reserved.

Microsoft, Windows, and Windows NT are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

The names of actual companies and products mentioned herein may be the trademarks of their respective owners.
 
Table Of Contents
1. Overview 3
2. Terms 3
3. Minifilter Installation 4
4. Minifilter Registration 4
5. Initiating filtering 4
6. Instance Notification Support 5
6.1. Setting up an Instance 5
6.2. Controlling Instance Teardown 6
6.3. Synchronizing Instance Detach 6
7. Callback Support 7
7.1. Callback data 7
7.2. Pre-Operation Callbacks 8
7.3. Post-Operation Callbacks 9
8. Manipulating Callback Data Parameters 11
8.1. I/O Parameter Block 11
8.2. Accessing buffer/MDL 12
8.3. Swapping buffers 13
9. Context Support 13
9.1. Context Registration 14
9.2. Context Creation APIs 14
9.3. Context Retrieval APIs 17
9.4. Context Freeing APIs 18
10. User Mode Communication 19
10.1. Filter Communication Port Object 19
10.2. Connecting to Communication Port from User Mode 20
10.3. Disconnecting from the Communication Port 21
10.4. Unload issues 21
11. File Name Support 21
11.1. Retrieving a File Name during an Operation 21
11.2. Additional Support for File Names 23
11.3. Interfaces for Name Providing Filters 23
12. Filter Initiated I/O 25
13. Rules for Unload/Unregister/Detach 27
14. Support Routines 27
15. Building a Minifilter 28

 
1. Overview
This document pertains to filter drivers between the I/O manager and the base filesystem, which can be local or remote.  It does not pertain to filter drivers that sit between the filesystem and the storage driver(s), such as FtDisk or DMIO.
We will refer to a file system filter driver written using the new model as a mini file system filter driver/minifilter.
The existing file system filters based on the sfilter sample
www.xDrv.com
XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
7楼#
发布于:2004-11-04 23:55
自己顶一下,免得几个兄弟太分散了……
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
8楼#
发布于:2004-11-05 14:00
不用这么辛苦,在精华区中有:)
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
jjw
jjw
驱动牛犊
驱动牛犊
  • 注册日期2001-11-01
  • 最后登录2008-11-05
  • 粉丝0
  • 关注0
  • 积分-6分
  • 威望5点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2005-04-12 20:23
好文章,再推一把354
jjw
游客

返回顶部