KeSetSystemAffinityThread 行为
KeSetSystemAffinityThread behavior
关于 KeSetSystemAffinityThread 函数的一些问题,因为 MSDN 比较简洁。
注意:我不能使用更完整的 KeSetSystemAffinityThreadEx,因为我仍然必须支持 Windows XP。
1) 如何恢复之前的亲和力?函数没有return旧值,如何获取?
2) 将 0 传递给函数是否恢复了默认的系统亲和性?我在一些论坛上发现了这样的断言,但我在微软官方文档中找不到。
3) 新线程的系统关联掩码是在 return 进入用户模式后保持不变,还是每次线程进入系统模式时都恢复为默认值?
4) 如果没有恢复以前的系统关联掩码会怎样?
(我宁愿 post 四个不同的问题,但在我看来它们太相互依赖了)
在 WinXP 中使用未记录的 KeRevertToUserAffinityThread(void)。快速搜索几乎没有关于 API 的信息,但我在 ReastOS 中找到了相同功能的实现:
ReactOS KeRevertToUserAffinityThread
它很简单所以我复制并粘贴到这里:
VOID NTAPI KeRevertToUserAffinityThread ( VOID )
{
KIRQL OldIrql;
PKPRCB Prcb;
PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
ASSERT(CurrentThread->SystemAffinityActive != FALSE);
/* Lock the Dispatcher Database */
OldIrql = KiAcquireDispatcherLock();
/* Set the user affinity and processor and disable system affinity */
CurrentThread->Affinity = CurrentThread->UserAffinity;
CurrentThread->IdealProcessor = CurrentThread->UserIdealProcessor;
CurrentThread->SystemAffinityActive = FALSE;
/* Get the current PRCB and check if it doesn't match this affinity */
Prcb = KeGetCurrentPrcb();
if (!(Prcb->SetMember & CurrentThread->Affinity))
{
/* Lock the PRCB */
KiAcquirePrcbLock(Prcb);
/* Check if there's no next thread scheduled */
if (!Prcb->NextThread)
{
/* Select a new thread and set it on standby */
NextThread = KiSelectNextThread(Prcb);
NextThread->State = Standby;
Prcb->NextThread = NextThread;
}
/* Release the PRCB lock */
KiReleasePrcbLock(Prcb);
}
/* Unlock dispatcher database */
KiReleaseDispatcherLock(OldIrql);
}
请注意,该函数不带任何参数,只是从当前 KTHREAD 结构中的某些元素恢复关联。我猜这回答了您的问题 1 和 2。只需不带参数调用此函数。我已经在 32 位 WinXP 中进行了测试并确认了这一点。问题 4 很简单,您的线程将继续 运行 使用您设置的处理器关联。
我不知道你的问题 3。但是用户模式和内核模式之间的切换很可能对当前有效的处理器关联没有影响,因为这是存储在 KTHREAD 结构中的东西。
关于 KeSetSystemAffinityThread 函数的一些问题,因为 MSDN 比较简洁。
注意:我不能使用更完整的 KeSetSystemAffinityThreadEx,因为我仍然必须支持 Windows XP。
1) 如何恢复之前的亲和力?函数没有return旧值,如何获取?
2) 将 0 传递给函数是否恢复了默认的系统亲和性?我在一些论坛上发现了这样的断言,但我在微软官方文档中找不到。
3) 新线程的系统关联掩码是在 return 进入用户模式后保持不变,还是每次线程进入系统模式时都恢复为默认值?
4) 如果没有恢复以前的系统关联掩码会怎样?
(我宁愿 post 四个不同的问题,但在我看来它们太相互依赖了)
在 WinXP 中使用未记录的 KeRevertToUserAffinityThread(void)。快速搜索几乎没有关于 API 的信息,但我在 ReastOS 中找到了相同功能的实现:
ReactOS KeRevertToUserAffinityThread
它很简单所以我复制并粘贴到这里:
VOID NTAPI KeRevertToUserAffinityThread ( VOID )
{
KIRQL OldIrql;
PKPRCB Prcb;
PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
ASSERT(CurrentThread->SystemAffinityActive != FALSE);
/* Lock the Dispatcher Database */
OldIrql = KiAcquireDispatcherLock();
/* Set the user affinity and processor and disable system affinity */
CurrentThread->Affinity = CurrentThread->UserAffinity;
CurrentThread->IdealProcessor = CurrentThread->UserIdealProcessor;
CurrentThread->SystemAffinityActive = FALSE;
/* Get the current PRCB and check if it doesn't match this affinity */
Prcb = KeGetCurrentPrcb();
if (!(Prcb->SetMember & CurrentThread->Affinity))
{
/* Lock the PRCB */
KiAcquirePrcbLock(Prcb);
/* Check if there's no next thread scheduled */
if (!Prcb->NextThread)
{
/* Select a new thread and set it on standby */
NextThread = KiSelectNextThread(Prcb);
NextThread->State = Standby;
Prcb->NextThread = NextThread;
}
/* Release the PRCB lock */
KiReleasePrcbLock(Prcb);
}
/* Unlock dispatcher database */
KiReleaseDispatcherLock(OldIrql);
}
请注意,该函数不带任何参数,只是从当前 KTHREAD 结构中的某些元素恢复关联。我猜这回答了您的问题 1 和 2。只需不带参数调用此函数。我已经在 32 位 WinXP 中进行了测试并确认了这一点。问题 4 很简单,您的线程将继续 运行 使用您设置的处理器关联。
我不知道你的问题 3。但是用户模式和内核模式之间的切换很可能对当前有效的处理器关联没有影响,因为这是存储在 KTHREAD 结构中的东西。