
Как узнать загруженность процессора

Как узнать загруженность процессора
Очередная интересная задача для программирования - узнать загруженность центрального процессора компьютера в процентах. Проблема в том, что система ни через какие API не предоставляет такого значения, как "загруженность", его просто нет. Зато есть хорошая функция GetSystemTimes, которая возвращает три значения: время, которое система бездействовала, время работы системы в режиме ядра и время работы системы в пользовательском режиме. Узнав разницу значений между этими таймингами за определенный интервал, можно определить загруженность процессора за этот интервал. На многоядерных системах эта функция возвращает суммарные значения по всем ядрам.
Первым делом в сегменте данных надо определить два комплекта структур FILETIME, они понадобятся в дальнейшем для работы с таймингами.
Code (Assembler) : Убрать нумерацию
- Old_IdleTime FILETIME
- Old_KernelTime FILETIME
- Old_UserTime FILETIME
- New_IdleTime FILETIME
- New_KernelTime FILETIME
- New_UserTime FILETIME
Code (Assembler) : Убрать нумерацию
- ; Получить первоначальные данные о времени работы системы
- invoke GetSystemTimes,Old_IdleTime,Old_KernelTime,Old_UserTime
Code (Assembler) : Убрать нумерацию
- ; Получить текущие данные о времени работы системы
- invoke GetSystemTimes,New_IdleTime,New_KernelTime,New_UserTime
- ; User = New_UserTime - Old_UserTime
- ; Kernel = New_KernelTime - Old_KernelTime
- ; Idle = New_IdleTime - Old_IdleTime
- ; Work = Kernel + User
- mov ecx,[New_KernelTime.dwLowDateTime]
- sub ecx,[Old_KernelTime.dwLowDateTime]
- mov eax,[New_UserTime.dwLowDateTime]
- sub eax,[Old_UserTime.dwLowDateTime]
- ; ECX = Work
- add ecx,eax
- mov eax,ecx
- ; EAX = Work - Idle
- sub eax,[New_IdleTime.dwLowDateTime]
- add eax,[Old_IdleTime.dwLowDateTime]
- ; CPU_Load = int((Work - Idle) * 100 / Work)
- xor edx,edx
- mov ebx,100
- mul ebx
- div ecx
- ; ....
- ; EAX - процент загруженности процессора за последний интервал времени
- ; ....
- ; Перенести новые данные вместо старых
- mov esi,New_IdleTime
- mov edi,Old_IdleTime
- mov ecx,6
- rep movsd
Похожий метод используется, когда надо узнать нагрузку на центральный процессор для конкретного приложения. Разница только в том, что вместо функции GetSystemTimes применяется GetProcessTimes, в остальном все то же самое.
В приложении пример программы с исходным текстом, показывающей общую загруженность центрального процессора с интервалом обновления в 1 секунду.
Просмотров: 2188 | Комментариев: 9

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(05.11.2020 в 16:22):
Купленный

Petya
(05.11.2020 в 16:15):
Купленный или как всё?

ManHunter
(01.09.2018 в 02:47):
Saladin, каждый вызов будет стопорить программу или поток на 1 секунду. Лучше делать отдельным тредом и в нем сохранять вычисленное значение загрузки проца в какой-нибудь расшаренной переменной. А из основного приложения запрашивать эту переменную по мере надобности с нужными интервалами.

Saladin
(31.08.2018 в 22:30):
Сваял версию под BCB6, юзайте на здоровье ;))
------------------------
int GetCPUUsage()
{
typedef BOOL (__stdcall *LPFN_GST)(LPFILETIME, LPFILETIME, LPFILETIME);
FILETIME Old_IdleTime, Old_KernelTime, Old_UserTime;
FILETIME New_IdleTime, New_KernelTime, New_UserTime;
FILETIME Idle, Kernel, User, Work;
LPFN_GST lpGetSystemTimes = (LPFN_GST)
GetProcAddress(GetModuleHandle("KERNEL32"), "GetSystemTimes");
if(lpGetSystemTimes(&Old_IdleTime, &Old_KernelTime, &Old_UserTime))
{
Sleep(1000);
if (lpGetSystemTimes(&New_IdleTime, &New_KernelTime, &New_UserTime))
{
User.dwLowDateTime = New_UserTime.dwLowDateTime - Old_UserTime.dwLowDateTime;
Kernel.dwLowDateTime = New_KernelTime.dwLowDateTime - Old_KernelTime.dwLowDateTime;
Idle.dwLowDateTime = New_IdleTime.dwLowDateTime - Old_IdleTime.dwLowDateTime;
Work.dwLowDateTime = Kernel.dwLowDateTime + User.dwLowDateTime;
int CPU_Load = (Work.dwLowDateTime - Idle.dwLowDateTime) * 100.0 / Work.dwLowDateTime;
return CPU_Load;
}
else
return 0;
}
else
// DWORD dwError = GetLastError();
return 0;
}
------------------------
int GetCPUUsage()
{
typedef BOOL (__stdcall *LPFN_GST)(LPFILETIME, LPFILETIME, LPFILETIME);
FILETIME Old_IdleTime, Old_KernelTime, Old_UserTime;
FILETIME New_IdleTime, New_KernelTime, New_UserTime;
FILETIME Idle, Kernel, User, Work;
LPFN_GST lpGetSystemTimes = (LPFN_GST)
GetProcAddress(GetModuleHandle("KERNEL32"), "GetSystemTimes");
if(lpGetSystemTimes(&Old_IdleTime, &Old_KernelTime, &Old_UserTime))
{
Sleep(1000);
if (lpGetSystemTimes(&New_IdleTime, &New_KernelTime, &New_UserTime))
{
User.dwLowDateTime = New_UserTime.dwLowDateTime - Old_UserTime.dwLowDateTime;
Kernel.dwLowDateTime = New_KernelTime.dwLowDateTime - Old_KernelTime.dwLowDateTime;
Idle.dwLowDateTime = New_IdleTime.dwLowDateTime - Old_IdleTime.dwLowDateTime;
Work.dwLowDateTime = Kernel.dwLowDateTime + User.dwLowDateTime;
int CPU_Load = (Work.dwLowDateTime - Idle.dwLowDateTime) * 100.0 / Work.dwLowDateTime;
return CPU_Load;
}
else
return 0;
}
else
// DWORD dwError = GetLastError();
return 0;
}

ManHunter
(29.08.2018 в 17:29):
Да почти то же самое, но работать придется с виртуальным реестром через задницу. И для получения значения загруженности процессора все равно придется точно так же снимать начальное и конечное значение за интервал времени, счетчики только другие.
В своей фразе я имел в виду что невозможно получить "мгновенное" значение загруженности процессора, как, например, можно получить объем занятой памяти по состоянию на сию секунду. Всегда придется считать загрузку за какой-то промежуток времени.
В своей фразе я имел в виду что невозможно получить "мгновенное" значение загруженности процессора, как, например, можно получить объем занятой памяти по состоянию на сию секунду. Всегда придется считать загрузку за какой-то промежуток времени.

wet
(29.08.2018 в 17:11):
Вообще то есть. Библиотека pdh.dll (Performance Data Helper) предоставляет доступ к различным счетчикам производительности, в т.ч. можно узнать загруженность процессора, даже для каждого ядра в отдельности.

ManHunter
(29.08.2018 в 08:26):
Ничего он не ругается, я сам DrWeb пользуюсь, всяко бы уж заметил.
Чистый аки слеза младенца: https://www.virustotal.com/#/f...30/detection
Чистый аки слеза младенца: https://www.virustotal.com/#/f...30/detection

Мойша
(28.08.2018 в 23:02):
И шо таки этому поцу не нравица ?

SHREEF
(28.08.2018 в 21:33):
Dr.Web ругается

Добавить комментарий
Заполните форму для добавления комментария
