Получение статистической информации о задании
Мы уже обсудили, как с помощью 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_INFORMA TION и 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. По этой причине, наверное, луч ше всегда именовать задания, даже если Вы и не собираетесь ссылаться на них по именам из других процессов.