Memory usage of current process in C

70,715

Solution 1

You can always just open the 'files' in the /proc system as you would a regular file (using the 'self' symlink so you don't have to look up your own pid):

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

Of course, you now have to parse the file to pick out the information you need.

Solution 2

The getrusage library function returns a structure containing a whole lot of data about the current process, including these:

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

However, the most up-to-date linux documentation says about these 3 fields

(unmaintained) This field is currently unused on Linux

which the manual then defines as:

Not all fields are completed; unmaintained fields are set to zero by the kernel. (The unmaintained fields are provided for compatibility with other systems, and because they may one day be supported on Linux.)

See getrusage(2)

Solution 3

This is a terribly ugly and non-portable way of getting the memory usage, but since getrusage()'s memory tracking is essentially useless on Linux, reading /proc/<pid>/statm is the only way I know of to get the information on Linux.

If anyone know of cleaner, or preferably more cross-Unix ways of tracking memory usage, I would be very interested in learning how.

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);
}

From the proc(5) man-page:

   /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)

Solution 4

I came across this post: http://appcrawler.com/wordpress/2013/05/13/simple-example-of-tracking-memory-using-getrusage/

Simplified version:

#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;
}

(tested in Linux 3.13)

Solution 5

#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);

I used this code but for some reason I get 0 all the time for all 4 printf()

Share:
70,715
scotts
Author by

scotts

Updated on December 06, 2021

Comments

  • scotts
    scotts over 2 years

    I need to get the memory usage of the current process in C. Can someone offer a code sample of how to do this on a Linux platform?

    I'm aware of the cat /proc/<your pid>/status method of getting memory usage, but I have no idea how to capture that in C.

    BTW, it's for a PHP extension I'm modifying (granted, I'm a C newbie). If there are shortcuts available within the PHP extension API, that would be even more helpful.

  • scotts
    scotts over 14 years
    Unfortunately the ru_idrss and ru_isrss data isn't availabe to my kernel (Ubuntu Hardy): linux.die.net/man/2/getrusage
  • James
    James over 12 years
    That's because, even in version 2.6, 10 years after POSIX.1, Linux still doesn't implement getrusage() except for a few fields. :-( Apparently, the only way to get the information is through kernel calls or reading /proc/<pid>/statm (see man 5 proc), which is completely unportable.
  • Not a Name
    Not a Name over 11 years
    Why are you using malloc for a statically sized struct?
  • Achim
    Achim about 7 years
    Unfortunately all data is showing 0 on my kernel (Debian Wheezy)
  • Achim
    Achim about 7 years
    Unfortunately also ru_maxrss is always showing 0 on my kernel (Debian Wheezy)
  • avl_sweden
    avl_sweden over 6 years
    This seems to work on Linux 4.12.4 at least. Although I wonder if maybe it's actually returning kilobytes.
  • Anti Earth
    Anti Earth over 6 years
    Caution; I don't handle when file doesn't exist
  • Matthieu M.
    Matthieu M. over 5 years
    The problem with this method is the measured in pages bit. If your process uses three 4kB pages, two 2MB pages and one 1GB page, it reports that 6 pages are used. Technically correct, but utterly useless to deduce the RSS in bytes.
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 4 years
    @MatthieuM. man proc also ways that "/proc/[pid]/status Provides much of the information in /proc/[pid]/stat and /proc/[pid]/statm", and that stat is used by ps, which then implies that both /proc/self/status and ps itself also share this problem, is that your understanding? Can you also cite something that shows that a single process can have pages of multiple different sizes? Thanks!
  • Matthieu M.
    Matthieu M. over 4 years
    @CiroSantilli新疆改造中心996ICU六四事件: I can only cite my own experience using manual huge pages + regular pages.
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 4 years
    @MatthieuM. thanks, I didn't know about mmap MAP_HUGE* :-) This is sad.
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 4 years
    One may also be tempted to parse /proc/self/stat which contains just numbers without labels, and according to man proc is used by ps. Or statm which is a stat subset for memory: stackoverflow.com/a/7212248/895245 Matthieu mentions that all those may be wrong for huge pages though: stackoverflow.com/questions/1558402/… I have to test it out.
  • mwag
    mwag over 4 years
    shouldn't int * be int and fscanf args be e.g. &currRealMem instead of currRealMem???
  • Anti Earth
    Anti Earth over 4 years
    @mwag No, this function "returns" by modifying the referenced primitives. You want to pass references of the caller primitives to this function. E.g. int a, b, c, d; getMemory(&a, &b, &c, &d);
  • mwag
    mwag over 4 years
    my bad, misread those int*s as being local vars rather than function args.
  • SRG
    SRG over 4 years
    Can you use & in C? I thought that was a C++ feature, isn't it? I mean, the function should accept a statm_t *result pointer instead. Am I missing something?
  • James
    James over 4 years
    &x is original C and means "the address pointing to the variable x". In C++, somewhat confusingly, the same character is used in type declarations to denote references.
  • GroovyDotCom
    GroovyDotCom almost 3 years
    Note that fopen of /proc/self/status can fail intermittently so check