需求:
软件功能用多进程实现, 由主进程创建若干子进程, 当主进程崩溃时,创建出来的子进程需要能够自动关闭。
方法1:
进程通信,子进程检查心跳包,一段时间没心跳包则退出进程。
缺点:
1.实现起来麻烦。
2.不支持第三方的程序,因为别人并未实现这些心跳机制。
3.依然存在可能程序有BUG, 子进程卡死不退出的现象。
方法2:
通过作业对象(Job Object来实现), 作业对象是Windows系统提供的对加入作业的进程做特定限制的内核对象,可以对作业中的进程组统一做时间片分配,网络,CPU亲缘性设置等。并且可以设置JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
标志,当作业对象释放,回收时(包括主进程崩溃),由操作系统来保证子进程结束。
相关API:
// 创建作业对象
HANDLE CreateJobObjectA(
[in, optional] LPSECURITY_ATTRIBUTES lpJobAttributes,
[in, optional] LPCSTR lpName
);
// 把进程加入作业。
BOOL AssignProcessToJobObject(
[in] HANDLE hJob,
[in] HANDLE hProcess
);
// 设置作业的限制内容
BOOL SetInformationJobObject(
[in] HANDLE hJob,
[in] JOBOBJECTINFOCLASS JobObjectInformationClass,
[in] LPVOID lpJobObjectInformation,
[in] DWORD cbJobObjectInformationLength
);
// 查询作业的限制内容。
BOOL QueryInformationJobObject(
[in, optional] HANDLE hJob,
[in] JOBOBJECTINFOCLASS JobObjectInformationClass,
[out] LPVOID lpJobObjectInformation,
[in] DWORD cbJobObjectInformationLength,
[out, optional] LPDWORD lpReturnLength
);
实现代码:
//========================= 创建进程 ============================//
char Proc_Path[] = "notepad.exe"; // 进程路径
STARTUPINFOA startup_info;
memset(&startup_info, 0x0, sizeof(startup_info));
startup_info.cb = sizeof(startup_info);
startup_info.wShowWindow = SW_SHOW;
PROCESS_INFORMATION proc_info;
memset(&proc_info, 0x0, sizeof(proc_info));
BOOL create_ok = CreateProcessA(
NULL,
Proc_Path,
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&startup_info,
&proc_info
);
//------------------------------------------------------------------------//
HANDLE job_handle = CreateJobObject(NULL, NULL); // 创建Job对象
BOOL add_job_ok = AssignProcessToJobObject(job_handle, proc_info.hProcess); // 把进程加入Job
//=========== 设置Job对象回收, 所有相关进程自动退出 ============//
JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info;
memset(&limit_info, 0x0, sizeof(limit_info));
limit_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; // job句柄回收时,所有加入job的进程都会强制结束。
BOOL set_auto_kill_ok = SetInformationJobObject(
job_handle,
JobObjectExtendedLimitInformation,
&limit_info,
sizeof(limit_info)
);
//-----------------------------------------------------------------//
/*
释放job对象, 调用后,所有相关进程都会退出。
假如程序崩溃没调用释放, 由系统回收,也能达到结束所有相关进程的效果。
在多进程系统中,这个特性必用,应对出现僵尸子进程的现象。
*/
CloseHandle(job_handle);