lohcve
驱动牛犊
驱动牛犊
  • 注册日期2007-08-31
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分400分
  • 威望41点
  • 贡献值0点
  • 好评度40点
  • 原创分0分
  • 专家分0分
阅读:1719回复:8

避免重入问题

楼主#
更多 发布于:2007-11-09 20:16
楚狂人的教程第2版14节讲到避免重入的问题:
-------------------------
但重入绝对不是问题本身.你可以自由的利用重入实现你的功能,但是你必须避免死递归.如果我能判断这个请求是我自己发出的,我则跳过,这时重入虽然发生,但是对我并没有影响:
NTSTATUS SfCreate(…)
{

if(这个IRP 不由我的驱动自己发出)
{
ZwCreateFile(…);   // <- 这里会导致发出Irp, 并再次被我们过滤到, 等于这里再次调用SfCreate(…)
}

}
-------------------------

最后讲到一个函数:
-------------------------
现在你可以在这个线程里做任何事情,包括生成文件,读写和其他操作等.得到IRP 的时候,可以通过线程id 来判断是否我们自己的线程,来跳过重入问题:
BOOLEAN WITIsMyThread(IN PWIT_THREAD thread)
{
return (PsGetCurrentThreadId() == thread->tid);
}
-------------------------

我的疑问是在调用这个函数时,PWIT_THREAD类型的实参从哪里获取,是将thread声明为全局变量还是从Irp中获取?
如果是将thread声明为全局变量,那么一来不用传递这个参数,二来(我的猜测)这个全局变量有可能会在其他Irp到来时被修改。
如果是从Irp中获取,那么具体是从Irp的哪个字段获取?
或者还有其他的处理办法?想了好长时间这个地方实在没想通,请大家指教,谢谢。




wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
沙发#
发布于:2007-11-10 09:33
参考FILEDISK里的方法,把所有相关处理IRP排队到你的线程里处理,然后在你的DISPATCH里判断是否来自你线程的处理,然后。。。。。。
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
lohcve
驱动牛犊
驱动牛犊
  • 注册日期2007-08-31
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分400分
  • 威望41点
  • 贡献值0点
  • 好评度40点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-11-11 01:05
谢谢wowocock老牛,是的,我也是这么想的,但是你没理解我的意思,我现在的问题就是不知道怎样“在你的DISPATCH里判断是否来自你线程的处理”,也就是怎样调用WITIsMyThread这个函数来判断?具体的说就是在 return (PsGetCurrentThreadId() == thread->tid) 这个语句中,我可以调用PsGetCurrentThreadId()函数来获取当前线程的Id,这个没有问题;但是如何获取thread->tid呢,也就是如何得到创建这个重入Irp的线程(即PWIT_THREAD thread参数)呢?回到我楼顶提的问题,就是在创建我的线程的时候,将PWIT_THREAD线程的信息保存到将要重入的Irp中呢,还是将PWIT_THREAD线程变量声明为全局变量(当然是在创建线程之前声明),或者根本就不是我说的这两种办法,还有其他的途径??这样我才能在调用WITIsMyThread这个函数时得到我创建的PWIT_THREAD线程的Id,来跟PsGetCurrentThreadId()这个当前线程的Id进行比较啊。

说的很啰嗦了,希望表达清楚我的意思了。
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
地板#
发布于:2007-11-11 12:48
一般全局变量即可。
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
lohcve
驱动牛犊
驱动牛犊
  • 注册日期2007-08-31
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分400分
  • 威望41点
  • 贡献值0点
  • 好评度40点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-11-12 13:48
OK,都说是全局变量,那么2个疑问:
1。全局变量不用传递参数
BOOLEAN WITIsMyThread()
{
return (PsGetCurrentThreadId() == thread->tid);
}
这样就行了,thread反正是全局变量
2。既然thread是全局变量,就有可能会在其他相同类型Irp到来时被修改。(这个只是我的猜测,不知道会不会出现前一个Irp被阻塞,而新来的Irp却能被顺利处理的情况?还是说Irp一定会严格按顺序执行?)

主要是第1点吧,不太清楚楚狂人的意图,有点困惑,不知道wowocock是什么想法。
lohcve
驱动牛犊
驱动牛犊
  • 注册日期2007-08-31
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分400分
  • 威望41点
  • 贡献值0点
  • 好评度40点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-11-13 10:33
wowocock老兄,我一直在等待你的答案呢,怎么不说话了?
devia
论坛版主
论坛版主
  • 注册日期2005-05-14
  • 最后登录2016-04-05
  • 粉丝3
  • 关注0
  • 积分1029分
  • 威望712点
  • 贡献值1点
  • 好评度555点
  • 原创分8分
  • 专家分4分
6楼#
发布于:2007-11-13 22:14
这个线程是在DriverEntry中创建,然后不会销毁也不会发生改变,它就是等待事情来做。所以不用担心会被修改或改变!
人总在矛盾中徘徊。。。
lohcve
驱动牛犊
驱动牛犊
  • 注册日期2007-08-31
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分400分
  • 威望41点
  • 贡献值0点
  • 好评度40点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-11-14 16:08
哦,谢谢devia,我了解你的想法,按照你的意思,这个在DriverEntry中创建的线程thread是全局变量,对不对?

既然是全局变量,那么引用这个thread的函数无需传递这个参数,直接引用就可以了,对不对?也就是说 BOOLEAN WITIsMyThread(IN PWIT_THREAD thread) 和 NTSTATUS WITDoItInThread(IN PWIT_THREAD thread, IN OUT PVOID context, IN PWIT_DO
do_somthing) 这2个函数其实不用传递 IN PWIT_THREAD thread 这个参数,写成:
BOOLEAN WITIsMyThread()
{
return (PsGetCurrentThreadId() == thread->tid);
}

NTSTATUS WITDoItInThread(IN OUT PVOID context, IN PWIT_DO do_somthing)
{
…………
}
就可以了,对不对??
lohcve
驱动牛犊
驱动牛犊
  • 注册日期2007-08-31
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分400分
  • 威望41点
  • 贡献值0点
  • 好评度40点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2007-11-16 13:35
devia版主,怎么说两句也不说话了?
游客

返回顶部