什么是作业对象?
作业对象是Windows中用于将多个进程作为一个单元进行管理的机制。它允许你对一组进程进行统一的资源管理和控制。
1. 基本作业管理
#include <windows.h>
#include <iostream>
// 创建作业对象
HANDLE CreateJobObjectExample() {
HANDLE hJob = CreateJobObject(NULL, L"MyJobObject");
if (hJob == NULL) {
std::cout << "创建作业对象失败: " << GetLastError() << std::endl;
}
return hJob;
}2. 将进程添加到作业
BOOL AssignProcessToJob(HANDLE hJob, HANDLE hProcess) {
return AssignProcessToJobObject(hJob, hProcess);
}3. 设置作业限制
void SetJobLimits(HANDLE hJob) {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobLimits = {0};
// 设置基本限制
jobLimits.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_ACTIVE_PROCESS | // 限制活动进程数
JOB_OBJECT_LIMIT_PROCESS_TIME | // 限制进程时间
JOB_OBJECT_LIMIT_WORKINGSET; // 限制工作集大小
jobLimits.BasicLimitInformation.ActiveProcessLimit = 5; // 最多5个进程
jobLimits.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart =
10000000; // 每个进程最多运行1秒(100纳秒单位)
jobLimits.ProcessMemoryLimit = 100 * 1024 * 1024; // 100MB内存限制
jobLimits.BasicLimitInformation.MinimumWorkingSetSize = 4096;
jobLimits.BasicLimitInformation.MaximumWorkingSetSize = 16 * 1024 * 1024;
SetInformationJobObject(hJob,
JobObjectExtendedLimitInformation,
&jobLimits,
sizeof(jobLimits));
}4. 完整的作业管理示例
#include <windows.h>
#include <iostream>
#include <vector>
#include <string>
class JobManager {
private:
HANDLE m_hJob;
std::vector<PROCESS_INFORMATION> m_processes;
public:
JobManager() : m_hJob(NULL) {}
~JobManager() {
Cleanup();
}
bool Initialize(const wchar_t* jobName = nullptr) {
m_hJob = CreateJobObject(NULL, jobName);
if (!m_hJob) {
std::cout << "创建作业对象失败,错误代码: " << GetLastError() << std::endl;
return false;
}
// 设置作业在所有进程退出时自动终止
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobLimits = {0};
jobLimits.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if (!SetInformationJobObject(m_hJob,
JobObjectExtendedLimitInformation,
&jobLimits,
sizeof(jobLimits))) {
std::cout << "设置作业限制失败,错误代码: " << GetLastError() << std::endl;
CloseHandle(m_hJob);
m_hJob = NULL;
return false;
}
std::cout << "作业对象创建成功!" << std::endl;
return true;
}
bool CreateProcessInJob(const wchar_t* processPath, const wchar_t* commandLine = nullptr) {
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi = {0};
// 构建命令行
std::wstring fullCommandLine;
if (commandLine) {
fullCommandLine = commandLine;
} else {
fullCommandLine = processPath;
}
std::wcout << L"正在创建进程: " << fullCommandLine << std::endl;
if (!CreateProcessW(
processPath,
&fullCommandLine[0],
NULL, NULL, FALSE,
CREATE_SUSPENDED,
NULL, NULL, &si, &pi)) {
DWORD error = GetLastError();
std::cout << "创建进程失败,错误代码: " << error << std::endl;
// 常见错误处理
if (error == ERROR_FILE_NOT_FOUND) {
std::cout << "错误: 找不到指定的文件" << std::endl;
}
return false;
}
// 将进程添加到作业
if (!AssignProcessToJobObject(m_hJob, pi.hProcess)) {
DWORD error = GetLastError();
std::cout << "添加到作业失败,错误代码: " << error << std::endl;
TerminateProcess(pi.hProcess, 1);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return false;
}
// 恢复进程执行
ResumeThread(pi.hThread);
std::wcout << L"进程创建成功,PID: " << pi.dwProcessId << std::endl;
m_processes.push_back(pi);
return true;
}
void PrintJobInfo() {
JOBOBJECT_BASIC_ACCOUNTING_INFORMATION info = {0};
if (QueryInformationJobObject(m_hJob,
JobObjectBasicAccountingInformation,
&info,
sizeof(info),
NULL)) {
std::cout << "=== 作业信息 ===" << std::endl;
std::cout << "活动进程数: " << info.ActiveProcesses << std::endl;
std::cout << "总进程数: " << info.TotalProcesses << std::endl;
std::cout << "=================" << std::endl;
}
}
void TerminateAllProcesses() {
std::cout << "正在终止所有进程..." << std::endl;
TerminateJobObject(m_hJob, 0);
}
void WaitForAllProcesses(DWORD timeout = INFINITE) {
WaitForSingleObject(m_hJob, timeout);
}
void Cleanup() {
if (m_hJob) {
CloseHandle(m_hJob);
m_hJob = NULL;
}
for (auto& pi : m_processes) {
if (pi.hProcess) CloseHandle(pi.hProcess);
if (pi.hThread) CloseHandle(pi.hThread);
}
m_processes.clear();
}
};
// 改进的使用示例
int main() {
JobManager jobMgr;
if (jobMgr.Initialize(L"ExampleJob")) {
// 在作业中创建进程 - 使用完整路径
jobMgr.CreateProcessInJob(L"C:\\Windows\\System32\\notepad.exe");
jobMgr.CreateProcessInJob(L"C:\\Windows\\System32\\calc.exe");
// 显示作业信息
jobMgr.PrintJobInfo();
std::cout << "进程已启动,请检查任务管理器中的notepad和calculator进程" << std::endl;
std::cout << "按回车键终止所有进程并退出..." << std::endl;
// 确保输入被正确读取
std::cin.clear();
std::cin.get();
std::cout << "正在清理..." << std::endl;
jobMgr.TerminateAllProcesses();
jobMgr.WaitForAllProcesses(3000);
std::cout << "程序结束" << std::endl;
} else {
std::cout << "初始化失败,程序退出" << std::endl;
return 1;
}
return 0;
}重要规则:
进程只能属于一个作业
一旦分配,无法移除
子进程自动继承父进程的作业