首页
社区
课程
招聘
[求助]请教一下,多处理器下同步的问题,请大家进来看一下我的具体描述.请大家帮帮我
发表于: 2010-5-2 04:32 9259

[求助]请教一下,多处理器下同步的问题,请大家进来看一下我的具体描述.请大家帮帮我

2010-5-2 04:32
9259
我这样描述一下吧:假如有个系统调用被InlineHook了(函数开头的20个字节被改变了),我写了恢复InlineHook的代码,可是现在问题来了:在向内存写函数的原始代码的时候,如何屏蔽其他线程调用这个函数呢?如果原始代码没有完全写到内存中的话,一旦有线程调用,那肯定会蓝屏啊......

以上说的都是在Ring0环境下,并且是多CPU的机器.

最好方法通用一些......这样更容易移植......

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (28)
雪    币: 47
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
提升IRQL至DISPATCH_LEVEL行不行
2010-5-2 11:37
0
雪    币: 225
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
提升IRQL至DISPATCH_LEVEL,对于只有一个CPU的机器是可以的,多处理器下就不行了,有没有好办法啊?
2010-5-3 12:29
0
雪    币: 34
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
先把该函数头写成jmp到别的地方空循环或直接返回失败
自己KeDelayExecution一下,让别的线程运行完前20字节.
把前20字节改回来.
把函数头改回来.
2010-5-3 12:54
0
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
5
投递dpc、ipi。
参见windows内核调试子系统是怎么冻结别的cpu的。
2010-5-3 20:46
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
受 weolar的启发,想起在 <软件调试>里提到  kdEnterDebugger可以 让 系统进入单一任务状态,冻结其他cpu.它的调用链好像是这样的吧.

KdEnterDebugger->KeFreezeExcution->KeDisableInterrupt->_disable()
__INTRIN_INLINE void _disable(void)
{
        __asm__("cli");
}
2010-5-4 00:10
0
雪    币: 460
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
cli不也一样是对单CPU来说的吗?
可以看下关于spinlock..那个偶也没玩过
2010-5-5 20:10
0
雪    币: 225
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢大家.....

看来还是投递DPC会比较通用一些,起码移植性比较好一些.
2010-5-5 20:28
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
9
我查reactos,最后的disable()函数是这样的,但一个cli就可以冻结其他cpu。。我也比较困惑,不知道是不是reactos没有完全实现kdenterdebugger的功能
2010-5-5 22:16
0
雪    币: 334
活跃值: (78)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
楼上的是怎么得出一个CPU cli了, 冻结了其它CPU结论的?
2010-5-6 11:12
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
看reactos源码, 一路跟踪 KdEnterDebugger()下来发现此函数关键操作就一个cli,
可能reactos没有完全实现kdEnterDebugger()
2010-5-6 11:52
0
雪    币: 334
活跃值: (78)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
但是,wrk也是这样的
2010-5-6 12:20
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
13
哪位高人能给我们解惑下
2010-5-6 12:58
0
雪    币: 334
活跃值: (78)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
14
刚刚试了试, cli并不是理解的那样只本禁止本地中断, 我的双核系统在cli后, 其它CPU也不响应中断了
2010-5-6 14:14
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
15
cli应该是全局的吧,楼上也验证了这点.
我的疑惑不是这里,虽说所有cpu都不能响应中断,但并不是说所用cpu都停止运行了,它们还是仍然在继续跑(如果之前它们都在跑指令流的话).只是此时它们是没法处理可屏蔽中断了.
我想在关中断的情况下,只要指令流中有会引发软硬中断的系统调用,它们应该会很快被阻塞住,即被冻结.不知道是不是这样.

我猜测的流程是这样..
假设有cpu0 cpu1
当前线程在cpu0 上执行cli指令后,就继续执行后面的指令.cli执行后,cpu1并不是立即被冻结,而是继续在原有的指令流上跑,直到碰到会引发软硬中断的指令,因被关中断,就被阻塞住了,即被冻结.而指令流中引发软硬中断的指令出现的几率实在是太大了,随便一个系统调用就是一个软中断.所以,cpu1在关中断后会被迅速冻结.而cpu0则同时继续跑,直到后面的sti,然后两个cpu又一起运作.

没学过多核方面的咚咚,以上纯属猜测..抛砖引玉,还望深藏不露的大大们露一手
2010-5-6 15:05
0
雪    币: 225
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
我反汇编了一下KeFreezeExecution
lkd> u KeFreezeExecution
nt!KeFreezeExecution:
80500922 e869000000      call    nt!KeDisableInterrupts (80500990)
80500927 c705403f558004000000 mov dword ptr [nt!KiFreezeFlag (80553f40)],4  //设置了全局变量
80500931 c20800          ret     8                   //这函数没用到参数,为什么返回时会带一个8,不理解啊?难道KeFreezeExecution有参数,代码里没用到?

lkd> u KeDisableInterrupts L10
nt!KeDisableInterrupts:
80500990 9c              pushfd
80500991 58              pop     eax
80500992 2500020000      and     eax,200h         //这里和EFLAGS寄存器的IF位进行与操作,好象也不是测试IF位是否被清除.
80500997 c1e809          shr     eax,9                   //这里移位有什么意思啊?没看懂
8050099a fa              cli                                      //清除IF位
8050099b c3              ret

不明白?
2010-5-6 19:02
0
雪    币: 225
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
昨天看了大家的回复,今天特地去了书店看了<<软件调试>>,其中的关于蓝屏描述的那一章里,我在里面看到了一个信息:WINDOWS在蓝屏的时候会调用KiSendXXXX函数来冻结其他CPU.隔了几个小时回到家,这个函数全名想不起来了.....郁闷.似乎这个函数可以实现同步.....
2010-5-6 19:14
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
18
nt!KeFreezeExecution:
80500922 e869000000      call    nt!KeDisableInterrupts (80500990)
80500927 c705403f558004000000 mov dword ptr [nt!KiFreezeFlag (80553f40)],4  //设置了全局变量
80500931 c20800          ret     8                   //这函数没用到参数,为什么返回时会带一个8,不理解啊?难道KeFreezeExecution有参数,代码里没用到?

的确是有参数,楼主反汇编xp出来的代码也是一句cli,呵呵,那一句cli应该是能冻结其他cpu,估计就是我的那个理解吧。^_^
2010-5-7 00:41
0
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
19
你们都说错了。我还是说清楚吧,KeFreezeExecution在单核下确实只要cli就行了。
但在多核下肯定不行。事实上cpu的apic早就提供了ipi机制,也就是处理器间中断。

KeFreezeExecution首先判断本cpu有没有被中断,如果是则调用KiIpiServiceRoutine响应ipi例程。
否则调用KiIpiSend发送IPI中断。这是个NMI(不可屏蔽),别的cpu会由apic执行KiIpiServiceRoutine。
至于KiIpiSend是怎么个原理,这得看inter手册。我只记得是设置apic的某个寄存器……
关于这部分的详细实现可以看kgdb的代码(arch/x86/Kconfig和arch/x86/kernel都可以看看),虽然是linux的,但原理是相似的。
2010-5-7 11:10
0
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
20
另外再提一下,inline hook如果只需要修改8个字节一下,
intel提供了个lock cmpxchg8b qword ptr [xxx];指令可以原子操作,比用各种同步操作方便多了。
不过以防万一,记得cmpxchg8b完了后再刷新一下TLB。
2010-5-7 11:17
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
21
多谢weolar,解答疑惑,偶去狂补下ipi
2010-5-7 11:26
0
雪    币: 225
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
[QUOTE=weolar;803291]另外再提一下,inline hook如果只需要修改8个字节一下,
intel提供了个lock cmpxchg8b qword ptr [xxx];指令可以原子操作,比用各种同步操作方便多了。
不过以防万一,记得cmpxchg8b完了后再刷新一下TLB。[/QUOTE]

能说一下如何刷新TLB吗?感激万分.......
2010-5-7 21:37
0
雪    币: 75
活跃值: (688)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
23
miflushtlb(),
不知道干嘛要冲刷tlb,只是替换内存某区域的内容。又不涉及页面表项的改变
2010-5-7 23:00
0
雪    币: 97
活跃值: (43)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
提升IRQL本身是不是创建了自旋锁。个人认为在处理多CPU同步的问题,使用自旋锁是最明智的,其他同步事件都不好使。
2010-5-9 16:38
0
雪    币: 334
活跃值: (78)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
25
显然他说这话没经过大脑
2010-5-10 10:36
0
游客
登录 | 注册 方可回帖
返回
//