¿Cómo se determina el consumo de CPU y memoria desde el interior de un proceso?

Una vez tuve la tarea de determinar los siguientes parámetros de rendimiento desde dentro de una aplicación en ejecución:

  • Memoria virtual total disponible
  • Memoria virtual actualmente utilizada
  • La memoria virtual utilizada actualmente por mi proceso

  • RAM total disponible
  • RAM actualmente utilizada
  • RAM actualmente utilizada por mi proceso

  • % De CPU actualmente utilizado
  • % De CPU actualmente utilizado por mi proceso

El código tenía que ejecutarse en Windows y Linux. Aunque parece ser una tarea estándar, encontrar la información necesaria en los manuales (API de WIN32, documentos de GNU) y en Internet me llevó varios días, porque hay tanta información incompleta / incorrecta / desactualizada sobre este tema como para ser encontrado por ahí

Con el fin de evitar que otros pasen por el mismo problema, pensé que sería una buena idea reunir toda la información dispersa más lo que encontré por prueba y error aquí en un solo lugar.

Windows

Algunos de los valores anteriores están fácilmente disponibles a partir de la API WIN32 apropiada, solo los incluyo aquí para que estén completos. Otros, sin embargo, deben obtenerse de la biblioteca de ayuda de datos de rendimiento (PDH), que es un poco “intuitiva” y requiere un gran esfuerzo de prueba y error para ponerse a trabajar. (Al menos me tomó bastante tiempo, quizás solo he sido un poco estúpido …)

Nota: para mayor claridad, todas las comprobaciones de errores se han omitido en el siguiente código. ¡Verifique los códigos de retorno …!

  • Memoria virtual total:

    #include "windows.h" MEMORYSTATUSEX memInfo; memInfo.dwLength = sizeof(MEMORYSTATUSEX); GlobalMemoryStatusEx(&memInfo); DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile; 

    Nota: El nombre “TotalPageFile” es un poco engañoso aquí. En realidad, este parámetro proporciona el “Tamaño de memoria virtual”, que es el tamaño del archivo de intercambio más la memoria RAM instalada.

  • Memoria virtual actualmente utilizada:

    Mismo código que en “Total Virtual Memory” y luego

     DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile; 
  • Memoria virtual actualmente utilizada por el proceso actual:

     #include "windows.h" #include "psapi.h" PROCESS_MEMORY_COUNTERS_EX pmc; GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); SIZE_T virtualMemUsedByMe = pmc.PrivateUsage; 
  • Memoria Física Total (RAM):

    Mismo código que en “Total Virtual Memory” y luego

     DWORDLONG totalPhysMem = memInfo.ullTotalPhys; 
  • Memoria física actualmente utilizada:

     Same code as in "Total Virtual Memory" and then DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys; 
  • Memoria física actualmente utilizada por el proceso actual:

    Mismo código que en “Memoria virtual usada actualmente por el proceso actual” y luego

     SIZE_T physMemUsedByMe = pmc.WorkingSetSize; 
  • CPU actualmente utilizada:

     #include "TCHAR.h" #include "pdh.h" static PDH_HQUERY cpuQuery; static PDH_HCOUNTER cpuTotal; void init(){ PdhOpenQuery(NULL, NULL, &cpuQuery); // You can also use L"\\Processor(*)\\% Processor Time" and get individual CPU values with PdhGetFormattedCounterArray() 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 actualmente utilizada por el proceso actual:

     #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

En Linux, la elección que parecía obvia al principio era usar las API POSIX como getrusage (), etc. Pasé algún tiempo tratando de hacer que esto funcionara, pero nunca obtuve valores significativos. Cuando finalmente verifiqué las fonts del kernel, descubrí que aparentemente estas API todavía no están completamente implementadas a partir del kernel 2.6 de Linux.

Al final obtuve todos los valores a través de una combinación de lectura del pseudo sistema de archivos / proc y llamadas al kernel.

  • Memoria virtual total:

     #include "sys/types.h" #include "sys/sysinfo.h" struct sysinfo memInfo; sysinfo (&memInfo); long long totalVirtualMem = memInfo.totalram; //Add other values in next statement to avoid int overflow on right hand side... totalVirtualMem += memInfo.totalswap; totalVirtualMem *= memInfo.mem_unit; 
  • Memoria virtual actualmente utilizada:

    Mismo código que en “Total Virtual Memory” y luego

     long long virtualMemUsed = memInfo.totalram - memInfo.freeram; //Add other values in next statement to avoid int overflow on right hand side... virtualMemUsed += memInfo.totalswap - memInfo.freeswap; virtualMemUsed *= memInfo.mem_unit; 
  • Memoria virtual actualmente utilizada por el proceso actual:

     #include "stdlib.h" #include "stdio.h" #include "string.h" int parseLine(char* line){ // This assumes that a digit will be found and the line ends in " Kb". 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(){ //Note: this value is in KB! 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; } 
  • Memoria Física Total (RAM):

    Mismo código que en “Total Virtual Memory” y luego

     long long totalPhysMem = memInfo.totalram; //Multiply in next statement to avoid int overflow on right hand side... totalPhysMem *= memInfo.mem_unit; 
  • Memoria física actualmente utilizada:

    Mismo código que en “Total Virtual Memory” y luego

     long long physMemUsed = memInfo.totalram - memInfo.freeram; //Multiply in next statement to avoid int overflow on right hand side... physMemUsed *= memInfo.mem_unit; 
  • Memoria física actualmente utilizada por el proceso actual:

    Cambie getValue () en “Memoria virtual usada actualmente por el proceso actual” de la siguiente manera:

     int getValue(){ //Note: this value is in KB! 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 actualmente utilizada:

     #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){ //Overflow detection. Just skip this value. 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 actualmente utilizada por el proceso actual:

     #include "stdlib.h" #include "stdio.h" #include "string.h" #include "sys/times.h" #include "sys/vtimes.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){ //Overflow detection. Just skip this value. percent = -1.0; } else{ percent = (timeSample.tms_stime - lastSysCPU) + (timeSample.tms_utime - lastUserCPU); percent /= (now - lastCPU); percent /= numProcessors; percent *= 100; } lastCPU = now; lastSysCPU = timeSample.tms_stime; lastUserCPU = timeSample.tms_utime; return percent; } 

TODO: Otras plataformas

Asumiría que parte del código de Linux también funciona para Unixes, a excepción de las partes que leen el / pseudo sistema de archivos proc. Tal vez en Unix estas partes pueden ser reemplazadas por getrusage () y funciones similares? Si alguien con conocimientos de Unix pudiera editar esta respuesta y completar los detalles?

Mac OS X

Esperaba encontrar información similar para Mac OS X también. Como no estaba aquí, salí y lo desenterré yo mismo. Estas son algunas de las cosas que encontré. Si alguien tiene otras sugerencias, me encantaría escucharlas.

Memoria virtual total

Este es complicado en Mac OS X porque no usa una partición o archivo de intercambio preestablecido como Linux. Aquí hay una entrada de la documentación de Apple:

Nota: A diferencia de la mayoría de los sistemas operativos basados ​​en Unix, Mac OS X no usa una partición de intercambio preasignada para la memoria virtual. En cambio, usa todo el espacio disponible en la partición de arranque de la máquina.

Entonces, si quiere saber cuánta memoria virtual todavía está disponible, necesita obtener el tamaño de la partición raíz. Puedes hacer eso así:

 struct statfs stats; if (0 == statfs("/", &stats)) { myFreeSwap = (uint64_t)stats.f_bsize * stats.f_bfree; } 

Total Virtual actualmente utilizado

Llamar a systcl con la clave “vm.swapusage” proporciona información interesante sobre el uso de swap:

 sysctl -n vm.swapusage vm.swapusage: total = 3072.00M used = 2511.78M free = 560.22M (encrypted) 

No es que el uso de intercambio total que se muestra aquí pueda cambiar si se necesita más intercambio como se explica en la sección anterior. Entonces el total es en realidad el total del intercambio actual . En C ++, estos datos se pueden consultar de esta manera:

 xsw_usage vmusage = {0}; size_t size = sizeof(vmusage); if( sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0)!=0 ) { perror( "unable to get swap usage by calling sysctlbyname(\"vm.swapusage\",...)" ); } 

Tenga en cuenta que el “xsw_usage”, declarado en sysctl.h, parece no estar documentado y sospecho que existe una forma más portátil de acceder a estos valores.

Memoria virtual actualmente utilizada por mi proceso

Puede obtener estadísticas sobre su proceso actual utilizando la función task_info . Eso incluye el tamaño residente actual de su proceso y el tamaño virtual actual.

 #include 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; } // resident size is in t_info.resident_size; // virtual size is in t_info.virtual_size; 

RAM total disponible

La cantidad de RAM física disponible en su sistema está disponible usando la función del sistema sysctl como esta:

 #include  #include  ... int mib[2]; int64_t physical_memory; mib[0] = CTL_HW; mib[1] = HW_MEMSIZE; length = sizeof(int64_t); sysctl(mib, 2, &physical_memory, &length, NULL, 0); 

RAM actualmente utilizado

Puede obtener estadísticas de la memoria general de la función del sistema host_statistics .

 #include  #include  #include  #include  int main(int argc, const char * argv[]) { vm_size_t page_size; mach_port_t mach_port; mach_msg_type_number_t count; vm_statistics64_data_t vm_stats; mach_port = mach_host_self(); count = sizeof(vm_stats) / sizeof(natural_t); if (KERN_SUCCESS == host_page_size(mach_port, &page_size) && 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)page_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)page_size; printf("free memory: %lld\nused memory: %lld\n", free_memory, used_memory); } return 0; } 

Una cosa a tener en cuenta aquí es que hay cinco tipos de páginas de memoria en Mac OS X. Son las siguientes:

  1. Páginas con cable que están bloqueadas en su lugar y no pueden intercambiarse
  2. Las páginas activas que se cargan en la memoria física y serían relativamente difíciles de intercambiar
  3. Las páginas inactivas que se cargan en la memoria, pero que no se han usado recientemente y que tal vez ni siquiera se necesiten. Estos son candidatos potenciales para el intercambio. Esta memoria probablemente necesitaría enrojecerse.
  4. Páginas en caché que se han almacenado en caché de alguna manera y que es probable que se reutilicen fácilmente. La memoria en caché probablemente no requiera enjuague. Todavía es posible reactivar las páginas en caché
  5. Páginas gratuitas que son completamente gratis y listas para ser usadas.

Es bueno tener en cuenta que solo porque Mac OS X puede mostrar muy poca memoria libre real a veces que puede no ser una buena indicación de cuánto está listo para ser utilizado en poco tiempo.

RAM utilizada actualmente por mi proceso

Consulte la “Memoria virtual usada actualmente por mi proceso” más arriba. El mismo código aplica.

Linux

En Linux, esta información está disponible en el sistema de archivos / proc. No soy un gran admirador del formato de archivo de texto utilizado, ya que cada distribución de Linux parece personalizar al menos un archivo importante. Una mirada rápida como la fuente de ‘ps’ revela el desastre.

Pero aquí es donde encontrar la información que busca:

/ proc / meminfo contiene la mayoría de la información de todo el sistema que busca. Aquí parece en mi sistema; Creo que estás interesado en MemTotal , MemFree , SwapTotal y SwapFree :

 Anderson cxc # more /proc/meminfo MemTotal: 4083948 kB MemFree: 2198520 kB Buffers: 82080 kB Cached: 1141460 kB SwapCached: 0 kB Active: 1137960 kB Inactive: 608588 kB HighTotal: 3276672 kB HighFree: 1607744 kB LowTotal: 807276 kB LowFree: 590776 kB SwapTotal: 2096440 kB SwapFree: 2096440 kB Dirty: 32 kB Writeback: 0 kB AnonPages: 523252 kB Mapped: 93560 kB Slab: 52880 kB SReclaimable: 24652 kB SUnreclaim: 28228 kB PageTables: 2284 kB NFS_Unstable: 0 kB Bounce: 0 kB CommitLimit: 4138412 kB Committed_AS: 1845072 kB VmallocTotal: 118776 kB VmallocUsed: 3964 kB VmallocChunk: 112860 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 Hugepagesize: 2048 kB 

Para la utilización de la CPU, debe hacer un poco de trabajo. Linux hace disponible el uso general de la CPU desde el inicio del sistema; esto probablemente no es lo que le interesa. Si quiere saber cuál fue el uso de la CPU durante el último segundo, o 10 segundos, entonces necesita consultar la información y calcularla usted mismo.

La información está disponible en / proc / stat , que está documentado bastante bien en http://www.linuxhowtos.org/System/procstat.htm ; esto es lo que parece en mi caja de 4 núcleos:

 Anderson cxc # more /proc/stat 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 intr 37124247 ctxt 50795173133 btime 1218807985 processes 116889 procs_running 1 procs_blocked 0 

En primer lugar, debe determinar cuántas CPU (o procesadores, o núcleos de procesamiento) están disponibles en el sistema. Para hacer esto, cuente el número de entradas ‘cpuN’, donde N comienza en 0 e incrementa. No cuente la línea ‘cpu’, que es una combinación de las líneas cpuN. En mi ejemplo, puede ver cpu0 a través de cpu3, ​​para un total de 4 procesadores. A partir de ahora, puede ignorar cpu0..cpu3 y enfocarse solo en la línea ‘cpu’.

A continuación, debe saber que el cuarto número en estas líneas es una medida de tiempo de inactividad, y por lo tanto, el cuarto número en la línea ‘cpu’ es el tiempo total de inactividad para todos los procesadores desde el momento del arranque. Esta vez se mide en “jiffies” de Linux, que son 1/100 de segundo cada uno.

Pero no te importa el tiempo de inactividad total; te importa el tiempo de inactividad en un período determinado, por ejemplo, el último segundo. Calcule eso, necesita leer este archivo dos veces, con un intervalo de 1 segundo. Luego, puede hacer una diferencia del cuarto valor de la línea. Por ejemplo, si toma una muestra y obtiene:

 cpu 2330047 0 2365006 1063853632 9035 9463 96114 0 

Luego, un segundo después, obtienes esta muestra:

 cpu 2330047 0 2365007 1063854028 9035 9463 96114 0 

Reste los dos números, y obtendrá un diff de 396, lo que significa que su CPU había estado inactiva durante 3,96 segundos de los últimos 1,00 segundos. El truco, por supuesto, es que debes dividir por el número de procesadores. 3.96 / 4 = 0.99, y está su porcentaje de inactividad; 99% inactivo y 1% ocupado.

En mi código, tengo un buffer de 360 ​​entradas, y leo este archivo cada segundo. Eso me permite calcular rápidamente la utilización de la CPU durante 1 segundo, 10 segundos, etc., hasta 1 hora.

Para la información específica del proceso, debe buscar en / proc / pid ; si no le importa su pid, puede mirar en / proc / self.

La CPU utilizada por su proceso está disponible en / proc / self / stat . Este es un archivo de aspecto extraño que consiste en una sola línea; por ejemplo:

 19340 (whatever) S 19115 19115 3084 34816 19115 4202752 118200 607 0 0 770 384 2 7 20 0 77 0 266764385 692477952 105074 4294967295 134512640 146462952 321468364 8 3214683328 4294960144 0 2147221247 268439552 1276 4294967295 0 0 17 0 0 0 0 

Los datos importantes aquí son los 13 y 14 tokens (0 y 770 aquí). La 13va. Token es la cantidad de jiffies que el proceso ha ejecutado en modo de usuario, y la 14 es el número de jiffies que el proceso ha ejecutado en modo kernel. Agregue los dos juntos, y tiene la utilización total de la CPU.

De nuevo, tendrá que muestrear este archivo periódicamente y calcular la diferencia para determinar el uso de la CPU del proceso a lo largo del tiempo.

Editar: recuerde que cuando calcule la utilización de CPU de su proceso, debe tener en cuenta 1) el número de subprocesos en su proceso, y 2) la cantidad de procesadores en el sistema. Por ejemplo, si su proceso de un único subproceso usa solo el 25% de la CPU, eso podría ser bueno o malo. Bueno en un sistema de procesador único, pero malo en un sistema de 4 procesadores; esto significa que su proceso se ejecuta constantemente y usa el 100% de los ciclos de CPU disponibles para él.

Para la información de memoria específica del proceso, debe observar / proc / self / status, que se ve así:

 Name: whatever State: S (sleeping) Tgid: 19340 Pid: 19340 PPid: 19115 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 256 Groups: 0 1 2 3 4 6 10 11 20 26 27 VmPeak: 676252 kB VmSize: 651352 kB VmLck: 0 kB VmHWM: 420300 kB VmRSS: 420296 kB VmData: 581028 kB VmStk: 112 kB VmExe: 11672 kB VmLib: 76608 kB VmPTE: 1244 kB Threads: 77 SigQ: 0/36864 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: fffffffe7ffbfeff SigIgn: 0000000010001000 SigCgt: 20000001800004fc CapInh: 0000000000000000 CapPrm: 00000000ffffffff CapEff: 00000000fffffeff Cpus_allowed: 0f Mems_allowed: 1 voluntary_ctxt_switches: 6518 nonvoluntary_ctxt_switches: 6598 

Las entradas que comienzan con ‘Vm’ son las más interesantes:

  • VmPeak es el espacio de memoria virtual máximo utilizado por el proceso, en kB (1024 bytes).
  • VmSize es el espacio de memoria virtual actual utilizado por el proceso, en kB. En mi ejemplo, es bastante grande: 651,352 kB, o alrededor de 636 megabytes.
  • VmRss es la cantidad de memoria que se ha mapeado en el espacio de direcciones del proceso, o su tamaño de conjunto residente. Esto es sustancialmente más pequeño (420,296 kB, o alrededor de 410 megabytes). La diferencia: mi progtwig ha mapeado 636 MB a través de mmap (), pero solo ha accedido a 410 MB de él, y por lo tanto, solo se le han asignado 410 MB de páginas.

El único elemento del que no estoy seguro es el uso de Swapspace actualmente en mi proceso . No sé si esto está disponible.

en Windows puede obtener el uso de la CPU por el código siguiente:

 #include  #include  //------------------------------------------------------------------------------------------------------------------ // Prototype(s)... //------------------------------------------------------------------------------------------------------------------ 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) // ============== // Return a CHAR value in the range 0 - 100 representing actual CPU usage in percent. //---------------------------------------------------------------------------------------------------------------- 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; // we cannot directly use GetSystemTimes on C language /* add this line :: pfnGetSystemTimes */ s_pfnGetSystemTimes(&ft_sys_idle, /* System idle time */ &ft_sys_kernel, /* system kernel time */ &ft_sys_user); /* System user time */ CopyMemory(&ul_sys_idle , &ft_sys_idle , sizeof(FILETIME)); // Could been optimized away... CopyMemory(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME)); // Could been optimized away... CopyMemory(&ul_sys_user , &ft_sys_user , sizeof(FILETIME)); // Could been optimized away... 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; } //------------------------------------------------------------------------------------------------------------------ // Entry point //------------------------------------------------------------------------------------------------------------------ int main(void) { int n; GetSystemTimesAddress(); for(n=0;n<20;n++) { printf("CPU Usage: %3d%%\r",cpuusage()); Sleep(2000); } printf("\n"); return 0; } 

Linux

Una forma portátil de leer la memoria y cargar números es la llamada sysinfo

Uso

  #include  int sysinfo(struct sysinfo *info); 

DESCRIPCIÓN

  Until Linux 2.3.16, sysinfo() used to return information in the following structure: struct sysinfo { long uptime; /* Seconds since boot */ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ unsigned long totalram; /* Total usable main memory size */ unsigned long freeram; /* Available memory size */ unsigned long sharedram; /* Amount of shared memory */ unsigned long bufferram; /* Memory used by buffers */ unsigned long totalswap; /* Total swap space size */ unsigned long freeswap; /* swap space still available */ unsigned short procs; /* Number of current processes */ char _f[22]; /* Pads structure to 64 bytes */ }; and the sizes were given in bytes. Since Linux 2.3.23 (i386), 2.3.48 (all architectures) the structure is: struct sysinfo { long uptime; /* Seconds since boot */ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ unsigned long totalram; /* Total usable main memory size */ unsigned long freeram; /* Available memory size */ unsigned long sharedram; /* Amount of shared memory */ unsigned long bufferram; /* Memory used by buffers */ unsigned long totalswap; /* Total swap space size */ unsigned long freeswap; /* swap space still available */ unsigned short procs; /* Number of current processes */ unsigned long totalhigh; /* Total high memory size */ unsigned long freehigh; /* Available high memory size */ unsigned int mem_unit; /* Memory unit size in bytes */ char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */ }; and the sizes are given as multiples of mem_unit bytes. 

QNX

Dado que esto es como una “wikipage de código”, quiero agregar un código de la base de conocimientos de QNX (nota: este no es mi trabajo, pero lo revisé y funciona bien en mi sistema):

Cómo obtener el uso de la CPU en%: http://www.qnx.com/support/knowledgebase.html?id=50130000000P9b5

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include 

Cómo obtener la memoria gratuita (!): http://www.qnx.com/support/knowledgebase.html?id=50130000000mlbx

 #include  #include  #include  #include  #include  #include  int main( int argc, char *argv[] ){ struct stat statbuf; paddr_t freemem; stat( "/proc", &statbuf ); freemem = (paddr_t)statbuf.st_size; printf( "Free memory: %d bytes\n", freemem ); printf( "Free memory: %d KB\n", freemem / 1024 ); printf( "Free memory: %d MB\n", freemem / ( 1024 * 1024 ) ); return 0; } 

Mac OS X – CPU

Uso general de la CPU:

¿ Recuperar información del sistema en MacOS X? :

 #include  #include  #include  #include  static unsigned long long _previousTotalTicks = 0; static unsigned long long _previousIdleTicks = 0; // Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between // You'll need to call this at regular intervals, since it measures the load between // the previous call and the current one. float GetCPULoad() { host_cpu_load_info_data_t cpuinfo; mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpuinfo, &count) == KERN_SUCCESS) { unsigned long long totalTicks = 0; for(int i=0; i 0) ? ((float)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0); _previousTotalTicks = totalTicks; _previousIdleTicks = idleTicks; return ret; } 

Usé este código siguiente en mi proyecto C ++ y funcionó bien:

 static HANDLE self; static int numProcessors; SYSTEM_INFO sysInfo; double percent; numProcessors = sysInfo.dwNumberOfProcessors; //Getting system times information FILETIME SysidleTime; FILETIME SyskernelTime; FILETIME SysuserTime; ULARGE_INTEGER SyskernelTimeInt, SysuserTimeInt; GetSystemTimes(&SysidleTime, &SyskernelTime, &SysuserTime); memcpy(&SyskernelTimeInt, &SyskernelTime, sizeof(FILETIME)); memcpy(&SysuserTimeInt, &SysuserTime, sizeof(FILETIME)); __int64 denomenator = SysuserTimeInt.QuadPart + SyskernelTimeInt.QuadPart; //Getting process times information FILETIME ProccreationTime, ProcexitTime, ProcKernelTime, ProcUserTime; ULARGE_INTEGER ProccreationTimeInt, ProcexitTimeInt, ProcKernelTimeInt, ProcUserTimeInt; GetProcessTimes(self, &ProccreationTime, &ProcexitTime, &ProcKernelTime, &ProcUserTime); memcpy(&ProcKernelTimeInt, &ProcKernelTime, sizeof(FILETIME)); memcpy(&ProcUserTimeInt, &ProcUserTime, sizeof(FILETIME)); __int64 numerator = ProcUserTimeInt.QuadPart + ProcKernelTimeInt.QuadPart; //QuadPart represents a 64-bit signed integer (ULARGE_INTEGER) percent = 100*(numerator/denomenator); 

For Linux You can also use /proc/self/statm to get a single line of numbers containing key process memory information which is a faster thing to process than going through a long list of reported information as you get from proc/self/status

See http://man7.org/linux/man-pages/man5/proc.5.html

  /proc/[pid]/statm Provides information about memory usage, measured in pages. The columns are: size (1) total program size (same as VmSize in /proc/[pid]/status) resident (2) resident set size (same as VmRSS in /proc/[pid]/status) shared (3) number of resident shared pages (ie, backed by a file) (same as RssFile+RssShmem in /proc/[pid]/status) text (4) text (code) lib (5) library (unused since Linux 2.6; always 0) data (6) data + stack dt (7) dirty pages (unused since Linux 2.6; always 0)