Uso de memoria del proceso actual en C

7 minutos de lectura

avatar de usuario
escoceses

Necesito obtener el uso de memoria del proceso actual en C. ¿Alguien puede ofrecer un ejemplo de código de cómo hacer esto en una plataforma Linux?

soy consciente de la cat /proc/<your pid>/status método para obtener el uso de la memoria, pero no tengo idea de cómo capturar eso en C.

Por cierto, es para una extensión de PHP que estoy modificando (concedido, soy un novato en C). Si hay accesos directos disponibles dentro de la API de extensión de PHP, eso sería aún más útil.

avatar de usuario
coste y flete

los getrusage La función de biblioteca devuelve una estructura que contiene una gran cantidad de datos sobre el proceso actual, incluidos estos:

long   ru_ixrss;         /* integral shared memory size */
long   ru_idrss;         /* integral unshared data size */
long   ru_isrss;         /* integral unshared stack size */

Sin embargo, la documentación de Linux más actualizada dice acerca de estos 3 campos

(unmaintained) This field is currently unused on Linux

que el manual luego define como:

No todos los campos están completos; los campos no mantenidos son puestos a cero por el kernel. (Los campos no mantenidos se proporcionan para la compatibilidad con otros sistemas y porque es posible que algún día sean compatibles con Linux).

Ver recibir mensajes(2)

  • Desafortunadamente, los datos de ru_idrss y ru_isrss no están disponibles para mi kernel (Ubuntu Hardy): linux.die.net/man/2/getrusage

    – escoceses

    13 de octubre de 2009 a las 17:19

  • Desafortunadamente, todos los datos muestran 0 en mi kernel (Debian Wheezy)

    – Achim

    1 de marzo de 2017 a las 12:30

Siempre puede simplemente abrir los ‘archivos’ en el /proc system como lo haría con un archivo normal (usando el enlace simbólico ‘self’ para que no tenga que buscar su propio pid):

FILE* status = fopen( "/proc/self/status", "r" );

Por supuesto, ahora debe analizar el archivo para seleccionar la información que necesita.

  • Uno también puede tener la tentación de analizar /proc/self/stat que contiene solo números sin etiquetas, y de acuerdo con man proc es usado por ps. O statm el cual es un stat subconjunto para la memoria: stackoverflow.com/a/7212248/895245 Sin embargo, Matthieu menciona que todo eso puede estar mal para páginas grandes: stackoverflow.com/questions/1558402/… Tengo que probarlo.

    – Ciro Santilli Путлер Капут 六四事

    27 ago. 2019 a las 7:00

avatar de usuario
Jaime

Esta es una forma terriblemente fea y no portátil de obtener el uso de la memoria, pero dado que el seguimiento de la memoria de getrusage() es esencialmente inútil en Linux, leer /proc//statm es la única forma que conozco de obtener el información sobre Linux.

Si alguien conoce formas más limpias, o preferiblemente más cruzadas de Unix, de rastrear el uso de la memoria, estaría muy interesado en aprender cómo.

typedef struct {
    unsigned long size,resident,share,text,lib,data,dt;
} statm_t;

void read_off_memory_status(statm_t& result)
{
  unsigned long dummy;
  const char* statm_path = "/proc/self/statm";

  FILE *f = fopen(statm_path,"r");
  if(!f){
    perror(statm_path);
    abort();
  }
  if(7 != fscanf(f,"%ld %ld %ld %ld %ld %ld %ld",
    &result.size,&result.resident,&result.share,&result.text,&result.lib,&result.data,&result.dt))
  {
    perror(statm_path);
    abort();
  }
  fclose(f);
}

Desde la página de manual de proc(5):

   /proc/[pid]/statm
          Provides information about memory usage, measured in pages.  
          The columns are:

              size       total program size
                         (same as VmSize in /proc/[pid]/status)
              resident   resident set size
                         (same as VmRSS in /proc/[pid]/status)
              share      shared pages (from shared mappings)
              text       text (code)
              lib        library (unused in Linux 2.6)
              data       data + stack
              dt         dirty pages (unused in Linux 2.6)

  • El problema con este método es el medido en paginas poco. Si su proceso utiliza tres páginas de 4kB, dos páginas de 2MB y una página de 1GB, informa que se utilizan 6 páginas. Técnicamente correcto, pero completamente inútil para deducir el RSS en bytes.

    – Matthieu M.

    12 de noviembre de 2018 a las 13:25


  • @MatthieuM. man proc también maneras que “/proc/[pid]/status Proporciona gran parte de la información en /proc/[pid]/stat y /proc/[pid]/statm“, y esa estadística es utilizada por pslo que implica que ambos /proc/self/status y ps también comparten este problema, ¿es así como lo entiendes? ¿Puede también citar algo que muestre que un solo proceso puede tener páginas de varios tamaños diferentes? ¡Gracias!

    – Ciro Santilli Путлер Капут 六四事

    26 de agosto de 2019 a las 22:08


  • @CiroSantilli新疆改造中心996ICU六四事件: Solo puedo citar mi propia experiencia usando páginas manuales grandes + páginas normales.

    – Matthieu M.

    27 de agosto de 2019 a las 6:32

  • @MatthieuM. gracias no sabia nada mmap MAP_HUGE* 🙂 Esto es triste.

    – Ciro Santilli Путлер Капут 六四事

    27 de agosto de 2019 a las 6:58

  • Puedes usar & ¿C ª? Pensé que era una característica de C++, ¿no es así? Quiero decir, la función debería aceptar un statm_t *result puntero en su lugar. ¿Me estoy perdiendo de algo?

    – SRG

    10 de febrero de 2020 a las 16:46


avatar de usuario
lepe

Me encontré con esta publicación: http://appcrawler.com/wordpress/2013/05/13/simple-example-of-tracking-memory-using-getrusage/

Versión simplificada:

#include <sys/resource.h>
#include <stdio.h>

int main() {
  struct rusage r_usage;
  getrusage(RUSAGE_SELF,&r_usage);
  // Print the maximum resident set size used (in kilobytes).
  printf("Memory usage: %ld kilobytes\n",r_usage.ru_maxrss);
  return 0;
}

(probado en Linux 3.13)

avatar de usuario
jeff

#include <sys/resource.h>
#include <errno.h>

errno = 0;
struct rusage memory;
getrusage(RUSAGE_SELF, &memory);
if(errno == EFAULT)
    printf("Error: EFAULT\n");
else if(errno == EINVAL)
    printf("Error: EINVAL\n");
printf("Usage: %ld\n", memory.ru_ixrss);
printf("Usage: %ld\n", memory.ru_isrss);
printf("Usage: %ld\n", memory.ru_idrss);
printf("Max: %ld\n", memory.ru_maxrss);

Usé este código, pero por alguna razón obtengo 0 todo el tiempo para los 4 printf()

  • Esto se debe a que, incluso en la versión 2.6, 10 años después de POSIX.1, Linux aún no implementa getrusage() excepto en algunos campos. 🙁 Aparentemente, la única forma de obtener la información es a través de llamadas al kernel o leyendo /proc//statm (ver man 5 proc), que es completamente inportable.

    – Jaime

    27 de agosto de 2011 a las 2:39

  • ¿Por qué estás usando malloc para una estructura de tamaño estático?

    – No es un nombre

    27 de noviembre de 2012 a las 3:05

avatar de usuario
contra la tierra

Llegué tarde a la fiesta, pero esto podría ser útil para cualquier otra persona que busque los recuerdos residentes y virtuales (y sus valores máximos hasta ahora) en Linux.

Probablemente sea bastante terrible, pero hace el trabajo.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*
 * Measures the current (and peak) resident and virtual memories
 * usage of your linux C process, in kB
 */
void getMemory(
    int* currRealMem, int* peakRealMem,
    int* currVirtMem, int* peakVirtMem) {

    // stores each word in status file
    char buffer[1024] = "";

    // linux file contains this-process info
    FILE* file = fopen("/proc/self/status", "r");

    // read the entire file
    while (fscanf(file, " %1023s", buffer) == 1) {

        if (strcmp(buffer, "VmRSS:") == 0) {
            fscanf(file, " %d", currRealMem);
        }
        if (strcmp(buffer, "VmHWM:") == 0) {
            fscanf(file, " %d", peakRealMem);
        }
        if (strcmp(buffer, "VmSize:") == 0) {
            fscanf(file, " %d", currVirtMem);
        }
        if (strcmp(buffer, "VmPeak:") == 0) {
            fscanf(file, " %d", peakVirtMem);
        }
    }
    fclose(file);
}

  • Esto se debe a que, incluso en la versión 2.6, 10 años después de POSIX.1, Linux aún no implementa getrusage() excepto en algunos campos. 🙁 Aparentemente, la única forma de obtener la información es a través de llamadas al kernel o leyendo /proc//statm (ver man 5 proc), que es completamente inportable.

    – Jaime

    27 de agosto de 2011 a las 2:39

  • ¿Por qué estás usando malloc para una estructura de tamaño estático?

    – No es un nombre

    27 de noviembre de 2012 a las 3:05

avatar de usuario
suave

La estructura anterior se tomó de 4.3BSD Reno. No todos los campos son significativos bajo Linux. En Linux 2.4 solo se mantienen los campos ru_utime, ru_stime, ru_minflt y ru_majflt. Desde Linux 2.6, también se mantienen ru_nvcsw y ru_nivcsw.

http://www.atarininja.org/index.py/tags/code

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad