Windows 2012下获取并修改活动进程处理器组的技术问询
刚好之前做过类似的多处理器组相关的开发,给你梳理下具体的实现方案,不管是C++还是C#都能搞定:
一、获取进程所属的处理器组
不管是查询还是修改,第一步都得拿到合法的进程句柄,注意打开进程时要申请对应的权限。
C++实现方式
Windows提供了专门的处理器组API,用GetProcessGroupAffinity就能拿到进程关联的处理器组信息。步骤大概是:
- 用
OpenProcess打开目标进程,需要PROCESS_QUERY_INFORMATION权限 - 调用
GetProcessGroupAffinity,先传入0获取需要的缓冲区大小,再分配内存获取实际的组数据 - 处理完记得关闭进程句柄
示例代码:
#include <windows.h> #include <vector> #include <iostream> bool GetProcessProcessorGroups(DWORD processId, std::vector<WORD>& outGroups) { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId); if (hProcess == NULL) { std::cerr << "OpenProcess failed: " << GetLastError() << std::endl; return false; } DWORD groupCount = 0; // 先获取需要的组数量 if (!GetProcessGroupAffinity(hProcess, &groupCount, NULL)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { std::cerr << "GetProcessGroupAffinity failed: " << GetLastError() << std::endl; CloseHandle(hProcess); return false; } } std::vector<GROUP_AFFINITY> groupAffinities(groupCount); if (!GetProcessGroupAffinity(hProcess, &groupCount, groupAffinities.data())) { std::cerr << "GetProcessGroupAffinity failed: " << GetLastError() << std::endl; CloseHandle(hProcess); return false; } outGroups.clear(); for (const auto& ga : groupAffinities) { outGroups.push_back(ga.Group); } CloseHandle(hProcess); return true; } // 调用示例 int main() { DWORD targetPid = 1234; // 替换成你的目标进程ID std::vector<WORD> groups; if (GetProcessProcessorGroups(targetPid, groups)) { std::cout << "Process " << targetPid << " belongs to groups: "; for (WORD g : groups) { std::cout << g << " "; } std::cout << std::endl; } return 0; }
C#实现方式
C#需要通过P/Invoke调用Windows API,先定义对应的结构体和函数声明:
using System; using System.Runtime.InteropServices; using System.Collections.Generic; public static class ProcessorGroupHelper { [StructLayout(LayoutKind.Sequential)] private struct GROUP_AFFINITY { public UIntPtr Mask; public ushort Group; private ushort Reserved1; private ushort Reserved2; private ushort Reserved3; } [DllImport("kernel32.dll", SetLastError = true)] private static extern bool GetProcessGroupAffinity(IntPtr hProcess, ref uint groupCount, [Out] GROUP_AFFINITY[] groupAffinities); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hObject); private const uint PROCESS_QUERY_INFORMATION = 0x0400; public static List<ushort> GetProcessGroups(uint processId) { var groups = new List<ushort>(); IntPtr hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, processId); if (hProcess == IntPtr.Zero) { Console.WriteLine($"OpenProcess failed: {Marshal.GetLastWin32Error()}"); return groups; } uint groupCount = 0; // 获取所需的组数量 if (!GetProcessGroupAffinity(hProcess, ref groupCount, null)) { int error = Marshal.GetLastWin32Error(); if (error != 122) // ERROR_INSUFFICIENT_BUFFER { Console.WriteLine($"GetProcessGroupAffinity failed: {error}"); CloseHandle(hProcess); return groups; } } var groupAffinities = new GROUP_AFFINITY[groupCount]; if (GetProcessGroupAffinity(hProcess, ref groupCount, groupAffinities)) { foreach (var ga in groupAffinities) { groups.Add(ga.Group); } } else { Console.WriteLine($"GetProcessGroupAffinity failed: {Marshal.GetLastWin32Error()}"); } CloseHandle(hProcess); return groups; } // 调用示例 public static void Main() { uint targetPid = 1234; // 替换成目标进程ID var groups = GetProcessGroups(targetPid); Console.WriteLine($"Process {targetPid} belongs to groups: {string.Join(", ", groups)}"); } }
二、更新指定进程的处理器组
修改进程的处理器组需要用到SetProcessGroupAffinity函数,注意打开进程时要申请PROCESS_SET_INFORMATION权限,而且不是所有进程都能修改(比如系统核心进程可能会因为权限不足失败)。
C++实现方式
示例代码:
#include <windows.h> #include <iostream> bool SetProcessProcessorGroup(DWORD processId, WORD targetGroup) { HANDLE hProcess = OpenProcess(PROCESS_SET_INFORMATION, FALSE, processId); if (hProcess == NULL) { std::cerr << "OpenProcess failed: " << GetLastError() << std::endl; return false; } GROUP_AFFINITY newGroupAffinity = {0}; newGroupAffinity.Group = targetGroup; // 设置该组的所有CPU核心掩码,也可以指定特定核心 newGroupAffinity.Mask = GetActiveProcessorMask(targetGroup); GROUP_AFFINITY oldGroupAffinity = {0}; if (!SetProcessGroupAffinity(hProcess, &newGroupAffinity, &oldGroupAffinity)) { std::cerr << "SetProcessGroupAffinity failed: " << GetLastError() << std::endl; CloseHandle(hProcess); return false; } std::cout << "Successfully changed process " << processId << " to group " << targetGroup << std::endl; std::cout << "Previous group: " << oldGroupAffinity.Group << std::endl; CloseHandle(hProcess); return true; } // 调用示例 int main() { DWORD targetPid = 1234; // 目标进程ID WORD targetGroup = 1; // 目标处理器组编号(从0开始) SetProcessProcessorGroup(targetPid, targetGroup); return 0; }
C#实现方式
同样通过P/Invoke实现,补充对应的函数声明:
using System; using System.Runtime.InteropServices; public static class ProcessorGroupHelper { // 之前的GROUP_AFFINITY结构体和其他函数声明保持不变 [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetProcessGroupAffinity(IntPtr hProcess, [In] GROUP_AFFINITY[] newGroupAffinity, [Out] GROUP_AFFINITY[] oldGroupAffinity); [DllImport("kernel32.dll")] private static extern UIntPtr GetActiveProcessorMask(ushort GroupNumber); private const uint PROCESS_SET_INFORMATION = 0x0200; public static bool SetProcessToGroup(uint processId, ushort targetGroup) { IntPtr hProcess = OpenProcess(PROCESS_SET_INFORMATION, false, processId); if (hProcess == IntPtr.Zero) { Console.WriteLine($"OpenProcess failed: {Marshal.GetLastWin32Error()}"); return false; } var newGroupAffinity = new GROUP_AFFINITY[1]; newGroupAffinity[0].Group = targetGroup; newGroupAffinity[0].Mask = GetActiveProcessorMask(targetGroup); var oldGroupAffinity = new GROUP_AFFINITY[1]; bool success = SetProcessGroupAffinity(hProcess, newGroupAffinity, oldGroupAffinity); if (success) { Console.WriteLine($"Successfully moved process {processId} to group {targetGroup}"); Console.WriteLine($"Previous group: {oldGroupAffinity[0].Group}"); } else { Console.WriteLine($"SetProcessGroupAffinity failed: {Marshal.GetLastWin32Error()}"); } CloseHandle(hProcess); return success; } // 调用示例 public static void Main() { uint targetPid = 1234; ushort targetGroup = 1; SetProcessToGroup(targetPid, targetGroup); } }
一些关键注意事项
- 处理器组编号从0开始,可以用
GetActiveProcessorGroupCount函数获取当前系统的活跃处理器组数量 - 打开进程时的权限一定要对应:查询用
PROCESS_QUERY_INFORMATION,修改用PROCESS_SET_INFORMATION,也可以直接用PROCESS_ALL_ACCESS(但不推荐,遵循最小权限原则) - 64核以上的Windows服务器通常会自动划分多个处理器组,你可以先通过任务管理器的“详细信息” tab,右键进程选择“设置相关性”来查看当前的组和核心分配,验证你的代码结果
- 有些受保护的系统进程(比如csrss.exe、smss.exe)无法修改,会返回权限不足的错误
内容的提问来源于stack exchange,提问作者evpo
相关产品推荐
相关产品推荐

