查询线程(而不是进程)处理器亲和力?

Windows上,可以为进程调用SetProcessAffinityMask,为线程调用SetThreadAffinityMask。 但是,Windows似乎只公开了GetProcessAffinityMask,而不是针对进程的单个线程的类似API。

我有一个multithreading程序,在运行时将各个线程绑定到处理器。 当我运行它,我想(外部)查询哪些处理器上运行的线程,以确保它正常工作。 我写了一个小的命令行工具来做到这一点。 但是我似乎无法find一种方法来寻找一个单独的线程绑定到哪个处理器或核心。

这显然必须是可能的; 我在网上看到adplus的debugging工具可以显示类似pstack的输出来显示线程关系。 并且Process Explorer在多处理器机器上显示一个线程标签,显示线程的“理想处理器”。

有谁知道如何查询这条信息?

您可以通过两次调用SetThreadAffinityMaskSetThreadAffinityMask 。 此函数返回传递的线程句柄的原始亲和力掩码

所以…用一个设置亲和力的掩码进行一次调用,然后再次调用恢复原始掩码。

这里是完整的C / C ++源代码,包括错误检查:

 DWORD GetThreadAffinityMask(HANDLE thread) { DWORD mask = 1; DWORD old = 0; // try every CPU one by one until one works or none are left while(mask) { old = SetThreadAffinityMask(thread, mask); if(old) { // this one worked SetThreadAffinityMask(thread, old); // restore original return old; } else { if(GetLastError() != ERROR_INVALID_PARAMETER) return 0; // fatal error, might as well throw an exception } mask <<= 1; } return 0; } 

此代码一次探测一个CPU,直到设置亲缘关系起作用(在这种情况下,我们现在知道原始的掩码!)或直到最初的1被移出DWORD 。 如果询问CPU不可用,则该函数将以ERROR_INVALID_PARAMETER失败,然后我们尝试下一个。 通常情况下,第一个CPU将工作,所以它是合理的效率。

如果这个函数失败了ERROR_INVALID_PARAMETER以外的任何东西,那就意味着我们对这个句柄没有足够的访问权限,或者系统有一些实际的问题,因为它不能满足我们的请求。 因此在这种情况下继续是没有意义的。

使用ThreadBasicInformation调用NtQueryInformationThread:

 typedef struct _THREAD_BASIC_INFORMATION { NTSTATUS ExitStatus; PTEB TebBaseAddress; CLIENT_ID ClientId; ULONG_PTR AffinityMask; KPRIORITY Priority; LONG BasePriority; } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; 

AFAIK没有记录的方式获得线程亲和力。

一个更快的方法是调用GetCurrentProcessorNumber看到msdn ,这将返回在调用此函数期间当前线程正在运行的处理器的数量。

c#代码:

 /// <summary> /// Retrieves the number of the processor the current thread was running on <para/> /// during the call to this function. /// </summary> /// <returns>The function returns the current processor number.</returns> [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern int GetCurrentProcessorNumber();