Windows 查询线程(不是进程)处理器关联?
在Windows上,可以为进程调用SetProcessAffinityMask,为线程调用SetThreadAffinityMask。但是,Windows似乎只公开GetProcessAffinityMask,而没有为进程的各个线程公开类似的API 我有一个多线程程序,在运行时将各个线程绑定到处理器。当我运行它时,我想(从外部)查询哪些线程正在哪个处理器上运行,以确保它正常工作。为此,我编写了一个小型命令行实用程序。但我似乎找不到一种方法来找到单个线程绑定到哪个处理器或内核 这显然是可能的;我在网上看到过关于adplus调试实用程序能够显示类似pstack的输出以显示线程相关性的描述。Process Explorer在多处理器机器上显示了一个线程选项卡,其中显示了线程的“理想处理器”Windows 查询线程(不是进程)处理器关联?,windows,multithreading,winapi,Windows,Multithreading,Winapi,在Windows上,可以为进程调用SetProcessAffinityMask,为线程调用SetThreadAffinityMask。但是,Windows似乎只公开GetProcessAffinityMask,而没有为进程的各个线程公开类似的API 我有一个多线程程序,在运行时将各个线程绑定到处理器。当我运行它时,我想(从外部)查询哪些线程正在哪个处理器上运行,以确保它正常工作。为此,我编写了一个小型命令行实用程序。但我似乎找不到一种方法来找到单个线程绑定到哪个处理器或内核 这显然是可能的;我在
有人知道如何查询这条信息吗?您可以通过两次调用来完成。此函数返回传递的线程句柄的原始关联掩码 所以。。。使用设置与一个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;
}
DWORD GetThreadAffinityMask(句柄线程)
{
DWORD掩码=1;
德沃德·奥尔德=0;
//一个接一个地尝试每个CPU,直到有一个可用或没有剩余
while(面具)
{
old=SetThreadAffinityMask(线程、掩码);
如果(旧)
{//这一次成功了
SetThreadAffinityMask(线程,旧);//还原原始
返老还童;
}
其他的
{
if(GetLastError()!=错误\u无效\u参数)
返回0;//致命错误,也可能引发异常
}
掩码调用NtQueryInformationThread,使用:
很抱歉,没有文档记录的方法来获取线程关联。更快的方法是调用GetCurrentProcessorNumber
查看在调用此函数期间,哪个将返回当前线程运行的处理器的编号
c#代码:
//
///检索当前线程运行的处理器的编号
///在调用此函数期间。
///
///该函数返回当前处理器编号。
[DllImport(“kernel32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
内部静态外部int GetCurrentProcessorNumber();
Damon,谢谢!-这非常有效。接下来的一个问题是:如果将其集成到tasklist样式的实用程序中,那么这会通过对每个正在运行的进程上的每个线程的关联掩码进行潜在的位攻击来影响进程性能吗?“正常”一个线程对所有CPU都有亲缘关系,包括第一个CPU。情况并非如此,这是非常不寻常的。因此,对SetThreadAffinityMask的调用通常不会超过2次。此外,我希望SetThreadAffinityMask的开销相当低,因为它可以或多或少地通过TEB直接设置信息,而TEB是oes甚至不需要上下文切换。因此性能应该类似于GetLastError函数。我不希望调用它一百次会产生任何明显的影响(尽管只有评测可以确定!)。仍然…您真的需要同时获取系统上所有线程的关联性吗?如果您特别要求,大多数任务列表样式的程序一次只查询一个线程的关联性。此外,如果确实存在问题,您仍然可以查询查询一个线程的工作线程中所有线程的关联性,并调用SwitchToTh读取或睡眠(0),然后查询下一个…并为每个更新向GUI线程发送消息。这将非常迅速地填充整个列表,并且没有任何影响。
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;
/// <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();