找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 975|回复: 13

《WIN64驱动教程》补充[10]:在高IRQL下执行需要低IRQL的代码

  [复制链接]

856

主题

2630

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36108
发表于 2014-6-7 02:04:47 | 显示全部楼层 |阅读模式
作者:Tesla.Angela

这篇文章,来源于一个一年多前的噩梦(具体原因参见主教程的WFP章节)。
选择在这个时候发这篇文章,目的是终结这个噩梦,顺带问候一下YaoHui这个SB。
题外话:如果对我的这个故事感兴趣,还可以看一下我在2013-8-5至2013-8-9之间发的微博。

言归正传,当你在一个高IRQL的线程A里,需要执行一个只能在低IRQL才能执行的操作,怎么办?
比如说,在IRQL=2的时候,需要用ZwReadFile。我曾经想过两个办法:
1.在调用ZwReadFile之前,调用KeLowerIrql降低IRQL,然后再调用ZwReadFile,最后使用KeRaiseIrql来恢复原来的IRQL。
2.发消息给另外一个线程B,让线程B执行,等线程B执行完,再让线程A继续执行。
结果如下:
1.蓝屏。
2.偶尔会正常,但没过多久就会死锁。如果在单CPU的系统里,一定死锁。
原因如下:
1.彻底破坏了系统环境。
2.在高IRQL的情况下,线程是不能切换的。当线程A、B都被同一个CPU执行时,会陷入“你等我我又等你”的状态。
这两个办法都行不通之后,我郁闷了很久。当时我直骂NT系统的设计人员,说他们是“用嘴来拉屎,用屁眼来吃饭”。

后来,我终于找到了这个问题的解决方案:使用“作业队列”。
我个人感觉“作业队列”其实是代码片段。等于发通知给系统,让系统的线程(IRQL=0)来执行你的代码片段。
“作业队列”,有人翻译为“劳务线程”、“作业线程”甚至“工人线程”。
不管怎么说,这玩意其实非常简单,只有两个相关函数:ExInitializeWorkItem、ExQueueWorkItem。
ExInitializeWorkItem用来初始化一个“作业队列”,而ExQueueWorkItem则用于执行。
这两个函数的原型如下:
VOID ExInitializeWorkItem
(
  _In_  PWORK_QUEUE_ITEM Item,         //一片NonPagedPool,大小为sizeof(WORK_QUEUE_ITEM)
  _In_  PWORKER_THREAD_ROUTINE Routine,//“代码片段”函数
  _In_  PVOID Context                  //传递给“代码片段”函数的参数
);
VOID ExQueueWorkItem
(
  _Inout_  PWORK_QUEUE_ITEM WorkItem,  //你之前申请的那片NonPagedPool
  _In_     WORK_QUEUE_TYPE QueueType   //作业队列的类型,个人感觉没啥区别,详情见MSDN
);


下面的例子是在WFP回调里调用ZwWriteFile。
但有一点我必须要说明:使用“作业队列”来执行代码是滞后的。时机是IRQL下降到0的时候。
换句话说,系统会“尽快”执行你的代码,“尽快”的意思是,一旦IRQL下降到0,你的代码就能马上被执行。

游客,如果您要查看本帖隐藏内容请回复

WFP_TEST_2.rar

7.8 KB, 下载次数: 13

售价: 2 水晶币  [记录]

评分

参与人数 1水晶币 +10 收起 理由
0xAA55 + 10 屌!

查看全部评分

头像被屏蔽

0

主题

29

回帖

0

精华

金牌会员

积分
976
发表于 2014-7-5 23:45:06 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

0

主题

37

回帖

0

精华

铜牌会员

积分
61
发表于 2024-1-1 17:01:42 | 显示全部楼层
学习了

0

主题

21

回帖

0

精华

铜牌会员

积分
53
发表于 2024-1-17 14:18:58 | 显示全部楼层
这个真的很有帮助,最早写的一个防火墙过滤数据包,想写日志到文件,一写就死机,就是这个害的。

5

主题

116

回帖

0

精华

铜牌会员

积分
174
发表于 2024-1-26 09:52:25 | 显示全部楼层
我来学习

0

主题

47

回帖

0

精华

贵宾会员

积分
89
发表于 2024-1-26 14:21:05 | 显示全部楼层
2024补充学习

1

主题

121

回帖

0

精华

铜牌会员

积分
181
发表于 2024-1-29 10:25:58 | 显示全部楼层
做好软件设计,尽量避免在高IRQL下执行低的代码,毕竟有WorkItem的滞后性

0

主题

4

回帖

0

精华

初来乍到

积分
2
发表于 2024-2-6 14:16:12 | 显示全部楼层
看看 学习

5

主题

116

回帖

0

精华

铜牌会员

积分
174
发表于 2024-2-7 11:16:24 | 显示全部楼层
PWORK_QUEUE_ITEM Item=kmalloc(sizeof(WORK_QUEUE_ITEM)); item 不用销毁吗?

856

主题

2630

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36108
 楼主| 发表于 2024-2-7 16:08:06 | 显示全部楼层
376408384 发表于 2024-2-7 11:16
PWORK_QUEUE_ITEM Item=kmalloc(sizeof(WORK_QUEUE_ITEM)); item 不用销毁吗?

The callback routine that was specified in the Routine parameter to ExInitializeWorkItem is called in a system context at IRQL PASSIVE_LEVEL. This caller-supplied routine is responsible for freeing the work item when it is no longer needed by calling ExFreePool or ExFreePoolWithTag.

来源:https://learn.microsoft.com/en-u ... wdm-exqueueworkitem

结论:需要自己释放,当年写代码时忘了,现在已经把你的提醒添加到主贴最末处。

3

主题

117

回帖

0

精华

铜牌会员

积分
286
发表于 2024-2-15 18:00:44 | 显示全部楼层
学习一下

0

主题

45

回帖

0

精华

铜牌会员

积分
53
发表于 2024-3-15 09:25:46 | 显示全部楼层
学习一下

1

主题

118

回帖

0

精华

金牌会员

积分
856
发表于 2024-3-29 10:23:18 | 显示全部楼层
感谢楼主,看看隐藏内容

0

主题

26

回帖

0

精华

贵宾会员

积分
15
发表于 2024-7-24 00:48:42 | 显示全部楼层
谢谢楼主
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表