Как определить потребление ЦП и памяти изнутри процесса
Описание проблемы: Получение параметров производительности в работающем приложении
У меня возникла задача определить следующие параметры производительности изнутри работающего приложения:
- Общая доступная виртуальная память
- Виртуальная память, в настоящее время используемая системой
- Виртуальная память, используемая моим процессом
- Общая доступная оперативная память (RAM)
- Оперативная память, в настоящее время используемая системой
- Оперативная память, используемая моим процессом
- Процент использования ЦП в данный момент
- Процент использования ЦП, используемого моим процессом
Код должен был работать как на Windows, так и на Linux. Несмотря на то, что на первый взгляд это кажется стандартной задачей, поиск необходимой информации в документации (WIN32 API, GNU docs), а также в Интернете занял у меня несколько дней. Я столкнулся с огромным количеством неполной, неверной и устаревшей информации по этой теме.
Для того чтобы сэкономить время другим разработчикам и избавить их от подобных трудностей, я подумал, что было бы полезно собрать всю разрозненную информацию, а также то, что я нашел методом проб и ошибок, в одном месте.
5 ответ(ов)
Windows
Некоторые из приведённых значений легко доступны через соответствующий Win32 API, и я просто перечисляю их здесь для полноты картины. Однако для получения других значений необходимо использовать библиотеку Performance Data Helper (PDH), которая может показаться несколько "неинтуитивной" и требует много проб и ошибок, чтобы начать работать. (По крайней мере, у меня ушло много времени, возможно, я просто не очень смышленый...)
Примечание: Для ясности весь код проверки ошибок опущен. Обязательно проверяйте коды возврата...!
Общая виртуальная память:
#include "windows.h" MEMORYSTATUSEX memInfo; memInfo.dwLength = sizeof(MEMORYSTATUSEX); GlobalMemoryStatusEx(&memInfo); DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
Примечание: Название "TotalPageFile" может сбивать с толку. На самом деле этот параметр даёт "Размер виртуальной памяти", который включает размер файла подкачки плюс установленную оперативную память.
Используемая виртуальная память:
Такой же код, как и для "Общей виртуальной памяти", а затем
DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
Используемая виртуальная память текущим процессом:
#include "windows.h" #include "psapi.h" PROCESS_MEMORY_COUNTERS_EX pmc; GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
Общая физическая память (ОП):
Такой же код, как и для "Общей виртуальной памяти", а затем
DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
Используемая физическая память:
Такой же код, как и для "Общей виртуальной памяти", а затем
DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
Используемая физическая память текущим процессом:
Такой же код, как и для "Используемой виртуальной памяти текущим процессом", а затем
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
Использование CPU в данный момент:
#include "TCHAR.h" #include "pdh.h" static PDH_HQUERY cpuQuery; static PDH_HCOUNTER cpuTotal; void init(){ PdhOpenQuery(NULL, NULL, &cpuQuery); PdhAddEnglishCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal); PdhCollectQueryData(cpuQuery); } double getCurrentValue(){ PDH_FMT_COUNTERVALUE counterVal; PdhCollectQueryData(cpuQuery); PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal); return counterVal.doubleValue; }
Использование CPU текущим процессом:
#include "windows.h" static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU; static int numProcessors; static HANDLE self; void init(){ SYSTEM_INFO sysInfo; FILETIME ftime, fsys, fuser; GetSystemInfo(&sysInfo); numProcessors = sysInfo.dwNumberOfProcessors; GetSystemTimeAsFileTime(&ftime); memcpy(&lastCPU, &ftime, sizeof(FILETIME)); self = GetCurrentProcess(); GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser); memcpy(&lastSysCPU, &fsys, sizeof(FILETIME)); memcpy(&lastUserCPU, &fuser, sizeof(FILETIME)); } double getCurrentValue(){ FILETIME ftime, fsys, fuser; ULARGE_INTEGER now, sys, user; double percent; GetSystemTimeAsFileTime(&ftime); memcpy(&now, &ftime, sizeof(FILETIME)); GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser); memcpy(&sys, &fsys, sizeof(FILETIME)); memcpy(&user, &fuser, sizeof(FILETIME)); percent = (sys.QuadPart - lastSysCPU.QuadPart) + (user.QuadPart - lastUserCPU.QuadPart); percent /= (now.QuadPart - lastCPU.QuadPart); percent /= numProcessors; lastCPU = now; lastUserCPU = user; lastSysCPU = sys; return percent * 100; }
Linux
На Linux очевидным на первый взгляд выбором было использование API POSIX, таких как getrusage()
и т.д. Я потратил некоторое время, пытаясь заставить это работать, но так и не получил значимых значений. Когда я наконец проверил исходный код ядра, я обнаружил, что эти API, видимо, ещё не полностью реализованы в версии ядра Linux 2.6!?
В итоге я получил все значения с помощью комбинации чтения из псевдо-файловой системы /proc
и вызовов ядра.
Общая виртуальная память:
#include "sys/types.h" #include "sys/sysinfo.h" struct sysinfo memInfo; sysinfo (&memInfo); long long totalVirtualMem = memInfo.totalram; totalVirtualMem += memInfo.totalswap; totalVirtualMem *= memInfo.mem_unit;
Используемая виртуальная память:
Такой же код, как и для "Общей виртуальной памяти", а затем
long long virtualMemUsed = memInfo.totalram - memInfo.freeram; virtualMemUsed += memInfo.totalswap - memInfo.freeswap; virtualMemUsed *= memInfo.mem_unit;
Используемая виртуальная память текущим процессом:
#include "stdlib.h" #include "stdio.h" #include "string.h" int parseLine(char* line){ int i = strlen(line); const char* p = line; while (*p <'0' || *p > '9') p++; line[i-3] = '\0'; i = atoi(p); return i; } int getValue(){ //Примечание: это значение в Кб! FILE* file = fopen("/proc/self/status", "r"); int result = -1; char line[128]; while (fgets(line, 128, file) != NULL){ if (strncmp(line, "VmSize:", 7) == 0){ result = parseLine(line); break; } } fclose(file); return result; }
Общая физическая память (ОП):
Такой же код, как и для "Общей виртуальной памяти", а затем
long long totalPhysMem = memInfo.totalram; totalPhysMem *= memInfo.mem_unit;
Используемая физическая память:
Такой же код, как и для "Общей виртуальной памяти", а затем
long long physMemUsed = memInfo.totalram - memInfo.freeram; physMemUsed *= memInfo.mem_unit;
Используемая физическая память текущим процессом:
Измените функцию getValue() в "Используемой виртуальной памяти текущим процессом", следующим образом:
int getValue(){ //Примечание: это значение в Кб! FILE* file = fopen("/proc/self/status", "r"); int result = -1; char line[128]; while (fgets(line, 128, file) != NULL){ if (strncmp(line, "VmRSS:", 6) == 0){ result = parseLine(line); break; } } fclose(file); return result; }
Использование CPU в данный момент:
#include "stdlib.h" #include "stdio.h" #include "string.h" static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle; void init(){ FILE* file = fopen("/proc/stat", "r"); fscanf(file, "cpu %llu %llu %llu %llu", &lastTotalUser, &lastTotalUserLow, &lastTotalSys, &lastTotalIdle); fclose(file); } double getCurrentValue(){ double percent; FILE* file; unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total; file = fopen("/proc/stat", "r"); fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow, &totalSys, &totalIdle); fclose(file); if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow || totalSys < lastTotalSys || totalIdle < lastTotalIdle){ percent = -1.0; // Обнаружение переполнения. Просто пропустите это значение. } else{ total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) + (totalSys - lastTotalSys); percent = total; total += (totalIdle - lastTotalIdle); percent /= total; percent *= 100; } lastTotalUser = totalUser; lastTotalUserLow = totalUserLow; lastTotalSys = totalSys; lastTotalIdle = totalIdle; return percent; }
Использование CPU текущим процессом:
#include "stdlib.h" #include "stdio.h" #include "string.h" #include "sys/times.h" static clock_t lastCPU, lastSysCPU, lastUserCPU; static int numProcessors; void init(){ FILE* file; struct tms timeSample; char line[128]; lastCPU = times(&timeSample); lastSysCPU = timeSample.tms_stime; lastUserCPU = timeSample.tms_utime; file = fopen("/proc/cpuinfo", "r"); numProcessors = 0; while(fgets(line, 128, file) != NULL){ if (strncmp(line, "processor", 9) == 0) numProcessors++; } fclose(file); } double getCurrentValue(){ struct tms timeSample; clock_t now; double percent; now = times(&timeSample); if (now <= lastCPU || timeSample.tms_stime < lastSysCPU || timeSample.tms_utime < lastUserCPU){ percent = -1.0; // Обнаружение переполнения. Просто пропустите
Вопрос: Как получить информацию о виртуальной и физической памяти на Mac OS X?
Ответ:
Получить информацию о виртуальной и физической памяти на Mac OS X можно несколькими способами. Однако стоит отметить, что в отличие от Linux, Mac OS X не использует предустановленное разделение подкачки; вместо этого он использует всё доступное пространство на загрузочном разделе. Ниже приведены различные методы для получения информации о памяти.
Общая виртуальная память
Чтобы узнать, сколько виртуальной памяти доступно, можно получить размер корневого раздела:
#include <sys/statvfs.h>
struct statfs stats;
if (0 == statfs("/", &stats))
{
uint64_t myFreeSwap = (uint64_t)stats.f_bsize * stats.f_bfree;
// Теперь myFreeSwap содержит доступное пространство
}
Объём текущей используемой виртуальной памяти
Вы можете получить информацию о использовании подкачки через sysctl
с использованием ключа "vm.swapusage":
sysctl -n vm.swapusage
Это выдаст общую информацию о подкачке, например:
vm.swapusage: total = 3072.00M used = 2511.78M free = 560.22M (encrypted)
В C++ это можно запросить следующим образом:
#include <sys/sysctl.h>
xsw_usage vmusage = {0};
size_t size = sizeof(vmusage);
if (sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0) != 0)
{
perror("Не удалось получить информацию о использовании подкачки");
}
Используемая виртуальная память для процесса
Информацию о текущем процессе можно получить с помощью функции task_info
:
#include <mach/mach.h>
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
if (KERN_SUCCESS != task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count))
{
return -1;
}
// t_info.resident_size содержит размер в памяти;
// t_info.virtual_size содержит текущий виртуальный размер.
Общая доступная физическая память
Количество доступной физической оперативной памяти можно получить с помощью sysctl
:
#include <sys/types.h>
#include <sys/sysctl.h>
int mib[2];
int64_t physical_memory;
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
size_t length = sizeof(int64_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);
Текущая используемая RAM
Общие статистические данные о памяти можно получить с помощью функции host_statistics
:
#include <mach/vm_statistics.h>
#include <mach/mach_types.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>
mach_port_t mach_port = mach_host_self();
vm_statistics64_data_t vm_stats;
mach_msg_type_number_t count = sizeof(vm_stats) / sizeof(natural_t);
if (KERN_SUCCESS == host_statistics64(mach_port, HOST_VM_INFO, (host_info64_t)&vm_stats, &count))
{
long long free_memory = (int64_t)vm_stats.free_count * (int64_t)vm_size;
long long used_memory = ((int64_t)vm_stats.active_count +
(int64_t)vm_stats.inactive_count +
(int64_t)vm_stats.wire_count) * (int64_t)vm_size;
printf("Свободная память: %lld\nИспользуемая память: %lld\n", free_memory, used_memory);
}
Важно
На Mac OS X существует пять типов страниц памяти:
- Заблокированные (Wired) страницы, которые нельзя выгнать.
- Активные (Active) страницы, загруженные в физическую память.
- Неактивные (Inactive) страницы, которые были загружены, но не используются.
- Кэшированные (Cached) страницы, которые могут быть легко повторно использованы.
- Свободные (Free) страницы, полностью свободные и готовые к использованию.
Следует помнить, что даже если Mac OS X показывает очень маленькое количество свободной памяти, это не всегда указывает на то, сколько памяти можно использовать в краткосрочной перспективе.
Таким образом, для получения информации о памяти на Mac OS X существует множество методов и подходов, и каждый из них может быть полезен в зависимости от ваших нужд.
В Linux эта информация доступна в файловой системе /proc. Я не сильно люблю текстовый формат, который используется, так как каждое дистрибутив Linux, похоже, настраивает как минимум один важный файл. Однако вот где можно найти интересующую вас информацию:
/proc/meminfo содержит большинство системных данных, которые вам нужны. Вот что у меня на системе; я думаю, вас интересуют MemTotal, MemFree, SwapTotal и SwapFree:
MemTotal: 4083948 kB
MemFree: 2198520 kB
Buffers: 82080 kB
Cached: 1141460 kB
SwapTotal: 2096440 kB
SwapFree: 2096440 kB
Что касается использования ЦП, здесь потребуется немного поработать. Linux предоставляет информацию о всём использовании CPU с момента запуска системы; это, вероятно, не то, что вас интересует. Если вы хотите узнать, каким было использование ЦП за последнюю секунду или десять секунд, вам нужно будет запрашивать эту информацию и вычислять её самостоятельно.
Эта информация доступна в /proc/stat, что довольно хорошо задокументировано на http://www.linuxhowtos.org/System/procstat.htm; вот как это выглядит на моем 4-ядерном компьютере:
cpu 2329889 0 2364567 1063530460 9034 9463 96111 0
cpu0 572526 0 636532 265864398 2928 1621 6899 0
cpu1 590441 0 531079 265949732 4763 351 8522 0
cpu2 562983 0 645163 265796890 682 7490 71650 0
cpu3 603938 0 551790 265919440 660 0 9040 0
Во-первых, вам нужно определить, сколько ЦП (или процессоров, или вычислительных ядер) доступно в системе. Для этого сосчитайте количество записей ‘cpuN’, где N начинается с 0 и увеличивается. Не учитывайте строку 'cpu', которая является комбинацией строк cpuN. В моем примере видны cpu0 по cpu3, итого 4 процессора. Теперь вы можете игнорировать cpu0..cpu3 и сосредоточиться только на строке 'cpu'.
Далее, вам нужно знать, что четвертое число в этих строках является измерением времени простоя, и, следовательно, четвертое число в строке 'cpu' - это общее время простоя для всех процессоров с момента загрузки. Это время измеряется в "jiffies" в Linux, которые составляют 1/100 секунды.
Но вам не интересно общее время простоя; вас интересует время простоя за определённый период, например, за последнюю секунду. Чтобы это вычислить, вам нужно прочитать этот файл дважды с интервалом в 1 секунду. Затем вы можете сравнить четвертое значение строки. Например, если вы сделали замер и получили:
cpu 2330047 0 2365006 1063853632 9035 9463 96114 0
А через секунду получили:
cpu 2330047 0 2365007 1063854028 9035 9463 96114 0
Вычтем два числа и получим разницу 396, что означает, что ваш ЦП был в режиме простоя 3.96 секунды из последней 1.00 секунды. Т.к. нужно делить на количество процессоров, 3.96 / 4 = 0.99, это ваш процент простоя; 99% простоя и 1% занятости.
В моем коде я использую кольцевой буфер из 360 записей, и читаю этот файл каждую секунду. Это позволяет мне быстро вычислять загрузку ЦП за 1 секунду, 10 секунд и так далее, вплоть до 1 часа.
Для информации, специфичной для процесса, нужно смотреть в /proc/pid; если вам не важен ваш pid, вы можете взглянуть в /proc/self.
Использование ЦП вашим процессом можно найти в /proc/self/stat. Этот файл выглядит странно, состоит из одной строки; например:
19340 (whatever) S 19115 19115 3084 34816 19115 4202752 118200 607 ...
Важные данные здесь — это 13-й и 14-й токены (0 и 770 в данном случае). 13-й токен — это количество jiffies, которое процесс использовал в пользовательском режиме, а 14-й — в режиме ядра. Складываете оба значения, и вы получаете общее использование ЦП.
Снова вам придется периодически считывать этот файл и вычислять разницу, чтобы определить использование ЦП процессом со временем.
Правка: помните, что при расчете использования ЦП для вашего процесса нужно учитывать 1) количество потоков в вашем процессе и 2) количество процессоров в системе. Например, если ваш однопоточный процесс использует лишь 25% ЦП, это может быть хорошо или плохо. Хорошо на однопроцессорной системе, но плохо на 4-процессорной системе; это означает, что ваш процесс работает постоянно, используя 100% всех доступных ему циклов ЦП.
Что касается информации о памяти, специфичной для процесса, нужно смотреть в /proc/self/status, который выглядит так:
Name: whatever
State: S (sleeping)
Tgid: 19340
Pid: 19340
PPid: 19115
...
VmPeak: 676252 kB
VmSize: 651352 kB
VmRSS: 420296 kB
...
Интересующие вас записи, начинающиеся с 'Vm':
- VmPeak — максимальный объем виртуальной памяти, используемой процессом, в кБ (1024 байт).
- VmSize — текущий объем виртуальной памяти, используемой процессом, в кБ.
- VmRSS — объем памяти, который был сопоставлен в адресное пространство процесса, или его резидентный набор.
Единственное, что я не уверен, это используемое место под файл подкачки процессом. Не знаю, доступна ли эта информация.
На Windows вы можете получить загрузку процессора с помощью следующего кода:
#include <windows.h>
#include <stdio.h>
//------------------------------------------------------------------------------------------------------------------
// Прототип(ы)...
//------------------------------------------------------------------------------------------------------------------
CHAR cpuusage(void);
//-----------------------------------------------------
typedef BOOL ( __stdcall * pfnGetSystemTimes)( LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
static pfnGetSystemTimes s_pfnGetSystemTimes = NULL;
static HMODULE s_hKernel = NULL;
//-----------------------------------------------------
void GetSystemTimesAddress()
{
if(s_hKernel == NULL)
{
s_hKernel = LoadLibrary(L"Kernel32.dll");
if(s_hKernel != NULL)
{
s_pfnGetSystemTimes = (pfnGetSystemTimes)GetProcAddress(s_hKernel, "GetSystemTimes");
if(s_pfnGetSystemTimes == NULL)
{
FreeLibrary(s_hKernel);
s_hKernel = NULL;
}
}
}
}
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
// cpuusage(void)
// ==============
// Возвращает значение типа CHAR в диапазоне от 0 до 100, представляющее текущую загрузку процессора в процентах.
//----------------------------------------------------------------------------------------------------------------
CHAR cpuusage()
{
FILETIME ft_sys_idle;
FILETIME ft_sys_kernel;
FILETIME ft_sys_user;
ULARGE_INTEGER ul_sys_idle;
ULARGE_INTEGER ul_sys_kernel;
ULARGE_INTEGER ul_sys_user;
static ULARGE_INTEGER ul_sys_idle_old;
static ULARGE_INTEGER ul_sys_kernel_old;
static ULARGE_INTEGER ul_sys_user_old;
CHAR usage = 0;
// Прямо использовать GetSystemTimes в языке C нельзя
/* Добавьте эту строку :: pfnGetSystemTimes */
s_pfnGetSystemTimes(&ft_sys_idle, /* Время простоя системы */
&ft_sys_kernel, /* Время ядра системы */
&ft_sys_user); /* Время пользователя системы */
CopyMemory(&ul_sys_idle , &ft_sys_idle , sizeof(FILETIME)); // Могло бы быть оптимизировано...
CopyMemory(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME)); // Могло бы быть оптимизировано...
CopyMemory(&ul_sys_user , &ft_sys_user , sizeof(FILETIME)); // Могло бы быть оптимизировано...
usage =
(
(
(
(
(ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
(ul_sys_user.QuadPart - ul_sys_user_old.QuadPart)
)
-
(ul_sys_idle.QuadPart-ul_sys_idle_old.QuadPart)
)
*
(100)
)
/
(
(ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
(ul_sys_user.QuadPart - ul_sys_user_old.QuadPart)
)
);
ul_sys_idle_old.QuadPart = ul_sys_idle.QuadPart;
ul_sys_user_old.QuadPart = ul_sys_user.QuadPart;
ul_sys_kernel_old.QuadPart = ul_sys_kernel.QuadPart;
return usage;
}
//------------------------------------------------------------------------------------------------------------------
// Точка входа
//------------------------------------------------------------------------------------------------------------------
int main(void)
{
int n;
GetSystemTimesAddress();
for(n=0; n<20; n++)
{
printf("Загрузка процессора: %3d%%\r", cpuusage());
Sleep(2000);
}
printf("\n");
return 0;
}
Этот код использует функцию GetSystemTimes
из библиотеки Kernel32.dll
, чтобы получить время простоя, времени ядра и времени пользователя системы. На основе этих значений рассчитывается процент загрузки процессора. В main
функция запускается в цикле, который печатает значение загрузки процессора каждые 2 секунды.
Как получить использование процессора в процентах на QNX
Если вы ищете способ получения использования процессора в процентах на QNX, вот код из базы знаний QNX, который работает на моем устройстве. Обратите внимание, что это не моя работа, но я проверял это и оно функционально.
Ссылка на источник: Как получить использование процессора
#include <atomic.h>
#include <libc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/iofunc.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <sys/syspage.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/debug.h>
#include <sys/procfs.h>
#include <sys/syspage.h>
#include <sys/neutrino.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <devctl.h>
#include <errno.h>
#define MAX_CPUS 32
static float Loads[MAX_CPUS];
static _uint64 LastSutime[MAX_CPUS];
static _uint64 LastNsec[MAX_CPUS];
static int ProcFd = -1;
static int NumCpus = 0;
int find_ncpus(void) {
return NumCpus;
}
int get_cpu(int cpu) {
int ret;
ret = (int)Loads[cpu % MAX_CPUS];
ret = max(0, ret);
ret = min(100, ret);
return(ret);
}
static _uint64 nanoseconds(void) {
_uint64 sec, usec;
struct timeval tval;
gettimeofday(&tval, NULL);
sec = tval.tv_sec;
usec = tval.tv_usec;
return(((sec * 1000000) + usec) * 1000);
}
int sample_cpus(void) {
int i;
debug_thread_t debug_data;
_uint64 current_nsec, sutime_delta, time_delta;
memset(&debug_data, 0, sizeof(debug_data));
for(i = 0; i < NumCpus; i++) {
/* Получаем время sutime для потока простоев #i+1 */
debug_data.tid = i + 1;
devctl(ProcFd, DCMD_PROC_TIDSTATUS, &debug_data, sizeof(debug_data), NULL);
/* Получаем текущее время */
current_nsec = nanoseconds();
/* Получаем разности между текущим и последним значениями */
sutime_delta = debug_data.sutime - LastSutime[i];
time_delta = current_nsec - LastNsec[i];
/* Вычисляем загрузку */
Loads[i] = 100.0 - ((float)(sutime_delta * 100) / (float)time_delta);
if(Loads[i] < 0) {
Loads[i] = 0;
}
/* Сохраняем для следующего цикла */
LastNsec[i] = current_nsec;
LastSutime[i] = debug_data.sutime;
}
return EOK;
}
int init_cpu(void) {
int i;
debug_thread_t debug_data;
memset(&debug_data, 0, sizeof(debug_data));
/* Открываем подключение к proc для общения. */
ProcFd = open("/proc/1/as", O_RDONLY);
if(ProcFd == -1) {
fprintf(stderr, "pload: Не удается получить доступ к procnto: %s\n", strerror(errno));
fflush(stderr);
return -1;
}
i = fcntl(ProcFd, F_GETFD);
if(i != -1) {
i |= FD_CLOEXEC;
if(fcntl(ProcFd, F_SETFD, i) != -1) {
/* Сохраняем это значение */
NumCpus = _syspage_ptr->num_cpu;
/* Получаем начальную точку для сравнений */
for(i = 0; i < NumCpus; i++) {
debug_data.tid = i + 1;
devctl(ProcFd, DCMD_PROC_TIDSTATUS, &debug_data, sizeof(debug_data), NULL);
LastSutime[i] = debug_data.sutime;
LastNsec[i] = nanoseconds();
}
return(EOK);
}
}
close(ProcFd);
return(-1);
}
void close_cpu(void){
if(ProcFd != -1) {
close(ProcFd);
ProcFd = -1;
}
}
int main(int argc, char* argv[]){
int i, j;
init_cpu();
printf("В системе: %d процессоров\n", NumCpus);
for(i = 0; i < 20; i++) {
sample_cpus();
for(j = 0; j < NumCpus; j++)
printf("Процессор #%d: %f\n", j, Loads[j]);
sleep(1);
}
close_cpu();
}
Как получить свободную (!) память на QNX
Если вам нужно узнать, сколько свободной памяти доступно на QNX, вы можете использовать следующий пример кода. Также это демонстрирует простоту работы с системными вызовами.
Ссылка на источник: Как получить свободную память
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
struct stat statbuf;
paddr_t freemem;
stat("/proc", &statbuf);
freemem = (paddr_t)statbuf.st_size;
printf("Свободная память: %d байт\n", freemem);
printf("Свободная память: %d КБ\n", freemem / 1024);
printf("Свободная память: %d МБ\n", freemem / (1024 * 1024));
return 0;
}
Эти примеры кода помогут вам просто и эффективно получить необходимые данные о загрузке процессора и свободной памяти в системе QNX.
Что такое "кэш-дружественный" код?
Как изменить цвет вывода echo в Linux
Разница между const int*, const int * const и int * const?
Почему переменные нельзя объявлять в операторе switch?
Разница между статическими и динамическими (разделяемыми) библиотеками?