在Windows上,您可以为进程调用SetProcessAffinityMask,为线程调用SetThreadAffinityMask。但是,Windows似乎只显示GetProcessAffinityMask而不是流程的各个线程的类似API。
我有一个多线程程序,可以在运行时将各个线程绑定到处理器。当我运行它时,我想(外部)查询哪些线程正在哪些处理器上运行,以确保它正常工作。我写了一个小的命令行实用程序来执行此操作。但我似乎无法找到一种方法来查找单个线程绑定的处理器或核心。
这显然必须是可能的;我在网上看到adplus调试实用程序的描述能够显示类似pstack的输出以显示线程关联。 Process Explorer在多处理器计算机上显示一个Threads选项卡,显示线程的“Ideal Processor”。
有谁知道如何查询这条信息?
答案 0 :(得分:6)
您可以通过两次拨打SetThreadAffinityMask
来完成此操作。此函数返回传递的线程句柄的原始关联掩码。
所以...用一个掩码设置一个调用,设置一个CPU的亲和力,然后再做一次调用来恢复原始掩码。
这是完整的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
,则意味着我们要么对句柄没有足够的访问权限,要么系统遇到一些实际问题,因为它无法满足我们的请求。因此,在这种情况下继续是没有意义的。
答案 1 :(得分:5)
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没有记录获得线程亲和力的方法。
答案 2 :(得分:0)
更快的方法是调用GetCurrentProcessorNumber
,看msdn,它将返回当前线程在调用此函数期间运行的处理器的编号。
c#code:
/// <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();