windows 核心编程第五章:演示作业的使用及获取统计信息

演示作业的使用及获取统计信息

演示作业的使用及获取统计信息

文章目录

  • 演示作业的使用及获取统计信息
  • 演示作业的使用及获取统计信息


演示作业的使用及获取统计信息

/*
演示作业的使用及获取统计信息
*/

#include 
#include 
#include 
#include 
#include  // for _alloca函数
#include  	


void EnumProcessIdsInJob(HANDLE hJob);//获取作业中当前的进程ID集
void StartRestrictedProcess();//利用作业对象对进程进程管理的演示

int _tmain()
{
	_tsetlocale(LC_ALL, TEXT("chs"));
	StartRestrictedProcess();
	return (0);
}
//获取作业中当前的进程ID集
void EnumProcessIdsInJob(HANDLE hJob)
{
	//先假设作业中的进程不会超过10个
	const int MAM_PROCESS_IDS = 10;

	//计算结构体和ID集所需的控件大小
	DWORD cb = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + 
		(MAM_PROCESS_IDS - 1) * sizeof(DWORD);

	//分配内存,注意_allocal是在栈(而不是堆上分配的,所有不需要释放)
	PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpil =
		(PJOBOBJECT_BASIC_PROCESS_ID_LIST)_alloca(cb);

	//估计最多的线程数
	pjobpil->NumberOfAssignedProcesses = MAM_PROCESS_IDS;

	//查询
	QueryInformationJobObject(hJob, JobObjectBasicProcessIdList, pjobpil, cb, &cb);

	//显示进程ID集
	for (DWORD x = 0; x < pjobpil->NumberOfProcessIdsInList; x++)
	{
		_tprintf(TEXT("process %d(ID = %d)\n"), x + 1, pjobpil->ProcessIdList[x]);
	}
}
//利用作业对象对进程进程管理的演示
void StartRestrictedProcess()
{
	//检查进程是否已经包含在作业中
	// 如果已经关联。就没犯法在换到另外一个作业对象中去

	/*屏蔽测试
	BOOL bInJob = FALSE;
	IsProcessInJob(GetCurrentProcess(), NULL, &bInJob);
	if (bInJob)
	{
		_tprintf(_T("Process already in a job\n"));
		return;
	}*/

	//创建作业内核对象
	HANDLE hJob = CreateJobObject(NULL,
		TEXT("MyRestrictedProcessJob"));

	//在作业中放入线程对象的一些限制规则
	//首先,设置基本限制
	JOBOBJECT_BASIC_LIMIT_INFORMATION jobli = { 0 };

	//进程总是运行在“空闲”优先级
	jobli.PriorityClass = IDLE_PRIORITY_CLASS;

	//该作业对象在用户模式下不能超过1ms的cpu时间
	jobli.PerJobUserTimeLimit.QuadPart = 1000 * 10000I64;
	//10000tick = 10000*100ns = 1ms
	//这里只增加了两个限制
	jobli.LimitFlags =
		JOB_OBJECT_LIMIT_PRIORITY_CLASS |
		JOB_OBJECT_LIMIT_JOB_TIME;

	SetInformationJobObject(hJob, JobObjectBasicLimitInformation,
		&jobli, sizeof(jobli));

	//其次,设置UI限制
	JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
	jobuir.UIRestrictionsClass = JOB_OBJECT_UILIMIT_NONE;//初始化为0

	//进程不能访问用户对象(比如窗口句柄)
	jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
	//进程不能关闭系统
	jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;

	SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &jobuir, sizeof(jobuir));

	//创建子进程并加入作业对象中
	//Note:进程被创建后,其线程要立刻挂起。再加入作业对象前,不能指向任何代码
	//这里作业对象的要求,否则,进程指向的那部分代码可能就不受作业对象的限制

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi;
	TCHAR szCmdLine[8];
	_tcscpy_s(szCmdLine, _countof(szCmdLine), TEXT("CMD"));

	BOOL bResult = CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE,
		CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
		NULL, NULL, &si, &pi);

	//将子进程加入到作业对象中
	//注意:当创建子进程时,子进程会自动加入到父进程所父的作业对象中

	AssignProcessToJobObject(hJob, pi.hProcess);

	//限制可以回复子进程的主线程,开始执行代码
	ResumeThread(pi.hThread);
	CloseHandle(pi.hThread);

	//枚举作业对象中的进程ID
	EnumProcessIdsInJob(hJob);

	//等待子进程结束或者作业对象所分配的cpu时间被用完
	HANDLE h[2];
	h[0] = pi.hProcess;
	h[1] = hJob;

	DWORD dw = WaitForMultipleObjects(2, h, FALSE, INFINITE);
	switch (dw - WAIT_OBJECT_0)
	{
	case 0:
		_tprintf(_T("The process has terminated...\n"));
		break;
	case 1:
		_tprintf(_T("All of the job's allotted CPU time was used...\n"));
		break;
	}

	FILETIME CreationTime;
	FILETIME ExitTime;
	FILETIME KernelTime;
	FILETIME UserTime;
	TCHAR szInfo[MAX_PATH];

	GetProcessTimes(pi.hProcess, &CreationTime, &ExitTime,
		&KernelTime, &UserTime);
	StringCchPrintf(szInfo, _countof(szInfo),
		TEXT("Kernel = %u|User = %u\n"),
		KernelTime.dwLowDateTime / 10000,
		UserTime.dwLowDateTime / 10000);

	CloseHandle(pi.hProcess);
	CloseHandle(hJob);

	_tprintf(szInfo);

	_tsystem(_T("pause"));
	return;
}

演示完毕,大家可以上机实验
windows 核心编程第五章:演示作业的使用及获取统计信息_第1张图片

你可能感兴趣的:(WINDOWS核心编程,windows)