Вот один из способов получения загрузки процессора процессом. Тут получаю загрузку собственным процессом, но можно и любым другим. По событию таймера получаю инфу о процессах с помощью NtQuerySystemInformation. Ищу свой процесс по pid'у. Смотрю у него время работы в пользовательском и ядерном режиме: UserTime и KernelTime. Эти значения получаю при каждом событии таймера. Работа процесса за время между событиями таймера - разность между предыдущим и последующим измерением. Я делю эту разность на интервал таймера и поручается загрузка процессора процессом. Чтобы получить общую загрузку процессора надо сложить ядерное и пользовательское время. Надеюсь понятно. Да, первое измерение будет неправильным, т.к. предыдущего измерения нет. В начале кода идут определения структур, нужные для вызова NtQuerySystemInformation.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
NTSTATUS = Cardinal;
const
SystemProcessesAndThreadsInformation = 5;
STATUS_SUCCESS = NTSTATUS($00000000);
type
PVM_COUNTERS = ^VM_COUNTERS;
VM_COUNTERS = packed record
PeakVirtualSize,
VirtualSize,
PageFaultCount,
PeakWorkingSetSize,
WorkingSetSize,
QuotaPeakPagedPoolUsage,
QuotaPagedPoolUsage,
QuotaPeakNonPagedPoolUsage,
QuotaNonPagedPoolUsage,
PagefileUsage,
PeakPagefileUsage: dword;
end;
PIO_COUNTERS = ^IO_COUNTERS;
IO_COUNTERS = packed record
ReadOperationCount,
WriteOperationCount,
OtherOperationCount,
ReadTransferCount,
WriteTransferCount,
OtherTransferCount: LARGE_INTEGER;
end;
PClientID = ^TClientID;
TClientID = packed record
UniqueProcess:cardinal;
UniqueThread:cardinal;
end;
PUnicodeString = ^TUnicodeString;
TUnicodeString = packed record
Length: Word;
MaximumLength: Word;
Buffer: PWideChar;
end;
PSYSTEM_THREADS = ^SYSTEM_THREADS;
SYSTEM_THREADS = packed record
KernelTime,
UserTime,
CreateTime: LARGE_INTEGER;
WaitTime: dword;
StartAddress: pointer;
ClientId: TClientId;
Priority,
BasePriority,
ContextSwitchCount: dword;
State: dword;
WaitReason: dword;
end;
PSYSTEM_PROCESSES = ^SYSTEM_PROCESSES;
SYSTEM_PROCESSES = packed record
NextEntryDelta, // Смещение следующей структуры от начала этой
ThreadCount: dword; // Количество потоков процесса
Reserved1 : array [0..5] of dword;
CreateTime, // Временные характеристики процесса
UserTime,
KernelTime: LARGE_INTEGER;
ProcessName: TUnicodeString; // Имя процесса
BasePriority: dword; // Базовый приоритет
ProcessId, // Идентификатор процесса - PID
InheritedFromProcessId, // PID родителя
HandleCount: dword; // Открытые дестрипторы
Reserved2: array [0..1] of dword;
// Счетчики с инфой об использовании памяти и системы ввода-вывода.
VmCounters: VM_COUNTERS;
IoCounters: IO_COUNTERS; // Windows 2000 only
// Массив структур с инфой о потоках процесса
Threads: array [0..0] of SYSTEM_THREADS;
end;
function NtQuerySystemInformation(dwSystemInformationClass: DWORD;
pSystemInformation: Pointer;
dwSystemInformationLength: DWORD;
var iReturnLength:DWORD): NTSTATUS;
stdcall;external 'ntdll.dll';
type
TForm1 = class(TForm)
Memo1: TMemo;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
end;
var
Form1: TForm1;
last_kernel_time, last_user_time, last_sys_counter: int64;
implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject);
var
pid: DWORD; // идентификатор процесса
ret: NTSTATUS;
pBuffer, pCur: PSYSTEM_PROCESSES;
ReturnLength: DWORD;
cur_kernel_time, cur_user_time: int64;
cpu_total_usage,cpu_user_usage,cpu_kernel_usage: Single;
begin
// Пролучаем pid нашего процесса, но можешь использовать и другой
pid := GetCurrentProcessId;
ReturnLength := 0;
// Запрашиваем размер требуемого буфера
ret := NtQuerySystemInformation(SystemProcessesAndThreadsInformation,
nil,
0,
ReturnLength);
// Резервируем буфер
pBuffer := AllocMem(ReturnLength);
// Получаем информацию о процессах в буфер
ret := NtQuerySystemInformation(SystemProcessesAndThreadsInformation,
pBuffer,
ReturnLength,
ReturnLength);
if ret = STATUS_SUCCESS then // Проверяем успешность выполнения запроса
begin
pCur := pBuffer; // Инициируем указатель на текущую структуру
// Проходим в цикле по всей цепочке структур
repeat
pCur := Ptr(DWORD(pCur) + pCur.NextEntryDelta);
// Ищем наш процесс
if pCur.ProcessId = pid then
begin
// Получаем инфу о времени работы нашего процесса
cur_user_time := int64(pCur.UserTime);
cur_kernel_time := int64(pCur.KernelTime);
// Вычисляем процентную загрузку процессора
cpu_user_usage := (cur_user_time - last_user_time) * 0.01 / Timer1.Interval;
cpu_kernel_usage := (cur_kernel_time - last_kernel_time) * 0.01 / Timer1.Interval;
cpu_total_usage := cpu_user_usage + cpu_kernel_usage;
// Выводим инфу в Memo, или куда хочешь
Memo1.Lines.Add ('Загрузка проца = ' + FloatToStr(cpu_total_usage) + ' %');
//запоминаем старые значения, для следующего расчета
last_kernel_time := cur_kernel_time;
last_user_time := cur_user_time;
end;
// Крутим цикл, пока есть следующая структура
until pCur.NextEntryDelta = 0;
end;
FreeMem(pBuffer);
end;
end.