上编文章已经说明如果,子进程不加入到作业中需要设置进程的flag字段为CREATE_BREAKAWAY_FROM_JOB
在创建进程的flag字段中找到CREATE_BREAKAWAY_FROM_JOB,其描述中说明如果进程关联了job,子进程不想关联就必须设置JOB_OBJECT_LIMIT_BREAKAWAY_OK。
JOBOBJECT_LIMIT_BREAKAWAY_OK 位于JOBOBJECT_BASIC_LIMIT_INFORMATION_结构体中
typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION {
LARGE_INTEGER PerProcessUserTimeLimit;
LARGE_INTEGER PerJobUserTimeLimit;
DWORD LimitFlags;
SIZE_T MinimumWorkingSetSize;
SIZE_T MaximumWorkingSetSize;
DWORD ActiveProcessLimit;
ULONG_PTR Affinity;
DWORD PriorityClass;
DWORD SchedulingClass;
} JOBOBJECT_BASIC_LIMIT_INFORMATION, *PJOBOBJECT_BASIC_LIMIT_INFORMATION;
如果要使用jobobject_limit_breakaway标记必须使用[**_JOBOBJECT_EXTENDED_LIMIT_INFORMATION**](https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-jobobject_extended_limit_information)结构体
结构体如下:
typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
IO_COUNTERS IoInfo;
SIZE_T ProcessMemoryLimit;
SIZE_T JobMemoryLimit;
SIZE_T PeakProcessMemoryUsed;
SIZE_T PeakJobMemoryUsed;
} JOBOBJECT_EXTENDED_LIMIT_INFORMATION, *PJOBOBJECT_EXTENDED_LIMIT_INFORMATION;
因此要使子进程不加入到作业中需要如下的代码设置
DWORD re;
BOOL Result;
HANDLE hJob1=CreateJobObject(NULL,L"hello");
_tprintf(L"hJob1 = %X GetLastError = %d\n",hJob1,GetLastError());
//创建对象
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info={0};
//设置为JOB_OBJECT_LIMIT_BREAKAWAY_OK
info.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_BREAKAWAY_OK;
//查询作业对象的信息
re =SetInformationJobObject(hJob1,JobObjectExtendedLimitInformation,(PVOID)&info,sizeof(info));
完整的代码
#include<Windows.h>
#include<tchar.h>
int _tmain()
{
/*
判断一个进程是否已经加入了一个作业的函数是:IsProcessInJob;
BOOL WINAPI IsProcessInJob(
__in HANDLE ProcessHandle,
__in_opt HANDLE JobHandle,
__out PBOOL Result
);
ProcessHandle: 要判断的进程句柄;
JobHandle: 看看进程是否加入到JobHandle这个作业中;
Result: 判断结果。
*/
DWORD re;
BOOL Result;
HANDLE hJob1=CreateJobObject(NULL,L"hello");
_tprintf(L"hJob1 = %X GetLastError = %d\n",hJob1,GetLastError());
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info={0};
info.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_BREAKAWAY_OK;
re =SetInformationJobObject(hJob1,JobObjectExtendedLimitInformation,(PVOID)&info,sizeof(info));
/*
BOOL WINAPI IsProcessInJob(
__in HANDLE ProcessHandle,
__in_opt HANDLE JobHandle,
__out PBOOL Result
);
ProcessHandle 需要检查确认的进程句柄 A。
JobHandle 作业句柄 B
Result 检查结果,如果是1,那么说明进程A已经被放入做也B,否则进程A没有被放到作业B中。
Return 成功,返回1,否则返回1
*/
re = IsProcessInJob(GetCurrentProcess(),NULL,&Result);
_tprintf(L" re = %d Result = %d\n",re,Result);
/////////////////////////////////////////////////////////
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
/*
BOOL WINAPI AssignProcessToJobObject(
__in HANDLE hJob,
__in HANDLE hProcess
);
hJob: 要将进程hProcess加入的那个作业的句柄
Process: 要加入到作业中的进程句柄
return: 成功返回1,否则返回0
*/
re=AssignProcessToJobObject(hJob1,GetCurrentProcess());
_tprintf(L" re = %d \n",re);
re = IsProcessInJob(GetCurrentProcess(),NULL,&Result);
_tprintf(L" re = %d currentProcess__Result = %d\n",re,Result);
// Start the child process.
if( !CreateProcess(L"Reloz.exe", // No module name (use command line)
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
NULL, // Set handle inheritance to FALSE
CREATE_BREAKAWAY_FROM_JOB, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
_tprintf(L"CreateProcess failed (%d).\n", GetLastError() );
return 0;
}
/////////////////////////////////////////
re = IsProcessInJob(pi.hProcess,hJob1,&Result);
_tprintf(L" re = %d pi.hProcess 子进程Result = %d\n",re,Result);
_gettchar();
CloseHandle(hJob1);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}