1、07Windows文件系统过滤驱动程序教程7Windows文件系统过滤驱动开发教程(7)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.一个数据结构.它的主要作
2、用是把实际存储媒介设备对象和文件系统上的卷设备对象联系起来. 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-RealDevic
3、e; ; 那么,从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设备对
4、象,当然是竹篮打水一场空了. 这里,你可以直接拷贝当前IO_STACK_LOCATION,然后向下发送请求,但在此之前,要先给irp分配一个完成函数.irp一旦完成,你的完成函数将被调用.这样的话,你可以在完成函数中得到Volume设备,并实施你的绑定过程. 这里要讨论一下中断级别的问题.常常碰到人问某函数只能在Passive Level调用是什么意思.总之我们的任何代码执行的时候,总是处在某个当前的中断级之中.某些系统调用只能在低级别中断级中执行.请注意,如果一个调用可以在高处运行,那么它能在低处运行,反过来则不行. 我们需要知道的只是我们关心Passive Level和Dispatch L
5、evel.而且Dispatch Level的中断级较高.一般ddk上都会标明,如果注明irq level=dispatch,那么你就不能在passive level的代码中调用它们了. 那么你如何判断当前的代码在哪个中断级别中呢?我一般是这么判断的:如果你的代码执行是由于应用程序(或者说上层)的调用而引发的,那么应该在Passive Level.如果你的代码执行是由于下层硬件而引发的,那么则可能在dispatch level. 希望不要机械的理解我的话!以上只是极为粗略的便于记忆的理解方法.实际的应用应该是这样的:所有的dispatch functions由于是上层发来的irp而导致的调用,所
6、以应该都是Passive Level,在其中你可以调用绝大多数系统调用.而如网卡的OnReceive,硬盘读写完毕,返回而导致的完成函数,都有可能在Dispatch级.注意都是有可能,而不是绝对是.但是一旦有可能,我们就应该按就是考虑. 好,现在我们发现,我们已经注册了完成函数,并且这个函数执行中可能是dispatch level. 现在面临的问题是,我们已经决定在完成函数中调用 IoAttachDeviceToDeviceStack来绑定Volume.而DDK说明有:Callers of IoAttachDeviceToDeviceStack must be running at IRQL
7、WorkerRoutine)(item-Parameter); 任务是一个数据结构,已经被我重定义为wd_work_item,wd_work_init能初始化它.初始化的时候你只需要填写一个你的任务的函数.同时一个context用来记录上下相关参数.(这是个空指针,你可以只想你任何想要的参数类型). 一般这个任务会自动执行,但是有时我们也想不插入队列,我们自己执行它.那么调用wd_work_run即可. 然后调用wd_work_queque插入工作者队列,之后会被执行.插入类型这里选择wd_work_delay. 希望你没有被这一串东西搞糊涂.现在我会写一个设置完成函数的函数.执行后,自动在P
8、assive 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 m
9、y_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.rn);
10、 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 *
11、context) wd_printf0(fsctl_comp: come in!rn); UNREFERENCED_PARAMETER(dev); UNREFERENCED_PARAMETER(irp); / 判断当前中断级 if(wd_get_cur_irql() wd_irql_passive) wd_printf0(fsctl_comp:into quque!rn); / 如果在passive更低的中断级别,必须插入延迟队列中运行 wd_work_queue(wd_work_item *)context,wd_work_delay); else / 否则可以直接执行 wd_printf0
12、(fsctl_comp:run directly!rn); 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函数显然会在P
13、assive level中执行.我们的系统也将保持稳定. work_complete函数将从context上下文指针中得到足够的参数,来完成对Volume的绑定. 希望你没有被弄昏头:),我们下回再分解.她含着笑,切着冰屑悉索的萝卜,她含着笑,用手掏着猪吃的麦糟,她含着笑,扇着炖肉的炉子的火,她含着笑,背了团箕到广场上去晒好那些大豆和小麦,大堰河,为了生活,在她流尽了她的乳液之后,她就用抱过我的两臂,劳动了。大堰河,深爱着她的乳儿;在年节里,为了他,忙着切那冬米的糖,为了他,常悄悄地走到村边的她的家里去,为了他,走到她的身边叫一声“妈”,大堰河,把他画的大红大绿的关云长贴在灶边的墙上,大堰河,
14、会对她的邻居夸口赞美她的乳儿;大堰河曾做了一个不能对人说的梦:在梦里,她吃着她的乳儿的婚酒,坐在辉煌的结彩的堂上,而她的娇美的媳妇亲切的叫她“婆婆”大堰河,深爱她的乳儿!大堰河,在她的梦没有做醒的时候已死了。她死时,乳儿不在她的旁侧,她死时,平时打骂她的丈夫也为她流泪,五个儿子,个个哭得很悲,她死时,轻轻地呼着她的乳儿的名字,大堰河,已死了,她死时,乳儿不在她的旁侧。大堰河,含泪的去了!同着四十几年的人世生活的凌侮,同着数不尽的奴隶的凄苦,同着四块钱的棺材和几束稻草,同着几尺长方的埋棺材的土地,同着一手把的纸钱的灰,大堰河,她含泪的去了。这是大堰河所不知道的:她的醉酒的丈夫已死去,大儿做了土匪,第二个死在炮火的烟里,第三,第四,第五而我,我是在写着给予这不公道的世界的咒语。当我经了长长的飘泊回到故土时,在山腰里,田野上,兄弟们碰见时,是比六七年
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1