Получение статистической информации о задании
Мы уже обсудили, как с помощью QueryInformationJobObject получить информацию о текущих ограничениях, установленных для задания. Этой функцией можно пользоваться и для получения статистической информации. Например, чтобы выяснить базовые учетные сведения, вызовите ее, передав JobObjeсtBasicAccountingInformation во втором параметре и адрес структуры JOBOBJECT_BASIC_ACCOUNTING_INFORMATION:
typedef struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
{
LARGE_INTEGER TotalUserTime;
LARGE_INTEGER TotalKernelTime;
LARGE_INTEGER ThisPeriodTotalUserTime;
LARGE_INTEGER ThisPeriodTotalKernelTime;
DWORD TotalPageFaultCount;
DWORD TotalProcesses;
DWORD ActiveProcesses;
DWORD TotalTerminatedProcesses;
} JOBOBJECT_BASIC_ACCOUNTING_INFORMATION, *PJOBOBJECT_BASIC_ACCOUNTING_INFORMATION;
Элементы этой структуры кратко описаны в таблице 5-3.
Элемент |
Описание | ||
TotalUserTtme |
Процессорное время, израсходованное процессами задания в пользовательском режиме | ||
TotalKernelTime |
Процессорное время, израсходованное процессами задания в режиме ядра | ||
ThisPeriodTotalUserTime |
То же, что TotalUserTime, но обнуляется, когда базовые oгpa ничения изменяются вызовом SetIniformationJobObject, а флаг JOB OBJECT_LIMIT_PRESERVE_JOB_TIME не используется | ||
ThisPeriodTotalKernelTime |
То же, что ThisPeriodTotalUserTime, но относится к процессор ному времени, израсходованному в режиме ядра | ||
TotalPageFaultCount |
Общее количество ошибок страниц, вызванных процессами задания | ||
TotalProcesses |
Общее число процессов, когда-либо выполнявшихся в зтом задании | ||
ActiveProcesses |
Текущее количество процессов в задании | ||
TotalTermtnatedProcesses |
Количество процессов, завершенных из-за превышения ими отведенного лимита процессорного времени |
Таблица 5-3. Элементы структуры JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
Вы можете извлечь те же сведения вместе с учетной информацией по вводу-выводу, передав JobObjectBasicAndIoAccountingInformation во втором параметре и адрес структуры JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION:
typedef struct JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION
{
JOBOBJECT_BASIC_ACCOUNTING_TNFORMATION Basiclnto;
IO_COUNTERS IoInfo;
} JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION;
Как видите, она просто возвращает JOBOBJECT_BASIC_ACCOUNTlNG_INFORMATION и IO_COUNTERS. Последняя структура показана на следующей странице.
typedef struct _IO_COUNTERS
{
ULONGlONG ReadOperationCount;
ULONGLONG WriteOperationCount;
ULONGLONG OtherOperationCount;
ULONGLONG ReadTransferCount;
ULONGLONG WriteTransferCount;
ULONGLONG OtheiTransferCount;
} IO_COUNTERS;
Она сообщает о числе операций чтения, записи и перемещения (а также о количестве байтов, переданных при выполнении этих операций). Данные относятся ко всем процессам в задании. Кстати, новая функция GetProcessIoCounters позволяет получить ту же информацию о процессах, не входящих ни в какие задания.
BOOL GetProcessIoCounters( HANDLE hProcess, PIO_GOUNTERS pToCounters);
QueryInformationJobObject такжe возвращает набор идентификаторов текущих про цессов в задании Но перед этим Вы должны прикинуть, сколько их там может быть, и выделить соответствующий блок памяти, где поместятся массив идентификаторов и структура JOBOBJECT_BASIC_PROCESS_ID_LIST
typedef struct _JOBOBJECT_BASIC_PROCESS_ID_LIST
{
DWORD NumberOfAssigncdProcessps;
DWORD NurrberOfProcessIdsInList;
DWORD ProcessIdList[1];
} JOBOBJECT_BASIC_PROCESS_ID_LIST, *PJOBOBJECT_BASIC_PROCESS_ID_LIST ;
В итоге, чтобы получить набор идентификаторов текущих процессов в задании, нужно написать примерно такой код:
void EnumProcessIdsInJob(HANDLE hjob)
{
// я исхожу из того, что количество процессов
// в этом задании никогда не превысит 10
#define MAX_PROCESS_TDS 10
// определяем размер блока памяти (в байтах)
// для хранения идентификаторов и структуры
DWORD cb = sizeof(JOBOBJECT_BASlC_PROCESS_ID LIST) + (MAX_PROCESS_IDS - 1) * sizeof(DWORD);
// выделяем этот блок памяти
PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpil = _alloca(cb);
// сообщаем функции, на какое максимальное число процессов
// рассчитана выделенная нами память pjobpil->NumberOfAssignedProcesseb = MAX_PROCESS_IDS;
// запрашиваем текущий список идентификаторов процессов
QuerylnformationJobObject(hjob, JobObjectBasicProcessIdList pjobpil, cb &cb);
// перечисляем идентификаторы процессов
for (int x =- 0; x < pjobpil->NumberOfProcessIdsInList; x++)
{
// используем
pjobpil->ProcessIdList[x]
}
// так как для выделения памяти мы вызывали _alloca,
// освобождать память нам не потребуется
}
Вот и все, что Вам удастся получить через эти функции, хотя на самом деле операционная система знает о заданиях гораздо больше. Эту информацию, которая хранится в специальных счетчиках, можно извлечь с помощью функций из библиотеки Performance Data Helper (PDH dIl) или через модуль Performance Monitor, подключаемый к Microsoft Management Console (MMC). Рис 5-3 иллюстрирует некоторые из доступных в системе счетчиков заданий (job object counters), а рис. 5-4 — счетчики, относящиеся к отдельным параметрам заданий (job object details counters) Заметьте, что в задании Jeff содержится четыре процесса calc, cmd, notepad и wordpad.
Рис. 5-3. MMC Performance Monitor счетчики задания
Рис. 5-4. MMC Performance Monitor счетчики, относящиеся к отдельным параметрам задания
Извлечь сведения из этих счетчиков Вы сможете только для тех заданий, которым были присвоены имена при вызове CreateJobObject. По этой причине, наверное, лучше всегда именовать задания, даже если Вы и не собираетесь ссылаться на них по именам из других процессов.