我正在Windows内核中运行一个线程,该线程通过共享内存与应用程序通信。一切正常,但由于睡眠循环导致通讯缓慢。我一直在研究自旋锁,互斥锁和互锁,但是我真的无法弄清楚这一点。我也考虑过Windows事件,但不知道该事件的性能。请提供一种更快的解决方案,以保持共享内存上的通信可能暗示Windows事件,这将是一个更快的解决方案。
内核代码
typedef struct _SHARED_MEMORY
{
BOOLEAN mutex;
CHAR data[BUFFER_SIZE];
} SHARED_MEMORY, *PSHARED_MEMORY;
ZwCreateSection(...)
ZwMapViewOfSection(...)
while (TRUE) {
if (((PSHARED_MEMORY)SharedSection)->mutex == TRUE) {
//... do work...
((PSHARED_MEMORY)SharedSection)->mutex = FALSE;
}
KeDelayExecutionThread(KernelMode, FALSE, &PollingInterval);
}
应用代码
OpenFileMapping(...)
MapViewOfFile(...)
...
RtlCopyMemory(&SM->data, WriteData, Size);
SM->mutex = TRUE;
while (SM->mutex != FALSE) {
Sleep(1); // Slow and removing it will cause an infinite loop
}
RtlCopyMemory(ReadData, &SM->data, Size);
更新1 目前,这是我想出的最快的解决方案:
while(InterlockedCompareExchange(&SM->mutex, FALSE, FALSE));
但是我觉得很有趣,您需要进行交换,并且没有仅用于比较的功能。
答案 0 :(得分:1)
您不想使用InterlockedCompareExchange。它会消耗CPU资源,使共享该物理内核的另一个线程可能需要的内核资源饱和,并使内核间总线饱和。
您确实需要做两件事:
1)编写一个InterlockedGet
函数并使用它。
2)防止循环消耗CPU资源,并防止循环最终解除阻塞时使用所有错误预测的分支之母。
对于1,至少在我上次检查时,此方法可在支持InterlockedCompareExchange
的所有编译器上起作用:
__inline static int InterlockedGet(int *val)
{
return *((volatile int *)val);
}
对于2,将其作为等待循环的主体:
__asm
{
rep nop
}
对于x86 CPU,此选项用于解决资源饱和和分支预测问题。
将它们放在一起:
while ((*(volatile int *) &SM->mutex) != FALSE) {
__asm
{
rep nop
}
}
如果不合适,请根据需要更改int
。