--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smapsum.c Fri Feb 23 23:54:45 2007 +0100
@@ -0,0 +1,248 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static char showtitle = 1;
+
+struct Filemap
+{
+ char name[300];
+ int size;
+ int rss;
+ int shared_clean;
+ int shared_dirty;
+ int private_clean;
+ int private_dirty;
+ enum {
+ PRIVATE,
+ SHARED
+ } type;
+ char readable;
+ char writable;
+ char executable;
+ int inode;
+ struct {
+ unsigned char major;
+ unsigned char minor;
+ } device;
+};
+
+struct Totals
+{
+ int size;
+ int rss;
+ int shared_clean;
+ int shared_dirty;
+ int private_clean;
+ int private_dirty;
+ char cmd[200];
+};
+
+
+static int readkb(const char *field, FILE *stream)
+{
+ int kb;
+ int res;
+ char line[200];
+
+ strcpy(line, field);
+ strcat(line, " %i kB\n");
+ res = fscanf(stream, line, &kb);
+ if (res != 1)
+ return -1;
+ return kb;
+}
+
+static int readsize(FILE *stream)
+{
+ return readkb("Size:", stream);
+}
+
+static int readrss(FILE *stream)
+{
+ return readkb("Rss:", stream);
+}
+
+static int readshared_clean(FILE *stream)
+{
+ return readkb("Shared_Clean:", stream);
+}
+
+static int readshared_dirty(FILE *stream)
+{
+ return readkb("Shared_Dirty:", stream);
+}
+
+static int readprivate_clean(FILE *stream)
+{
+ return readkb("Private_Clean:", stream);
+}
+
+static int readprivate_dirty(FILE *stream)
+{
+ return readkb("Private_Dirty:", stream);
+}
+
+static int readfilemap(FILE *stream, struct Filemap *map)
+{
+ int res;
+ char type;
+
+ unsigned int major;
+ unsigned int minor;
+
+ res = fscanf(stream, "%*x-%*x %c%c%c%c %*x %x:%x %i",
+ &map->readable,
+ &map->writable,
+ &map->executable,
+ &type,
+ &major,
+ &minor,
+ &map->inode);
+
+ if (res != 7)
+ return -1;
+
+ fgets(map->name, 300, stream);
+
+ map->device.major = major;
+ map->device.minor = minor;
+
+ if (type == 's')
+ map->type = PRIVATE;
+ else
+ map->type = SHARED;
+
+ if (map->readable == '-')
+ map->readable = 0;
+ if (map->writable == '-')
+ map->writable = 0;
+ if (map->executable == '-')
+ map->executable = 0;
+
+ map->size = readsize(stream);
+ if (map->size == -1)
+ return -2;
+ map->rss = readrss(stream);
+ if (map->rss == -1)
+ return -2;
+ map->shared_clean = readshared_clean(stream);
+ if (map->shared_clean == -1)
+ return -2;
+ map->shared_dirty = readshared_dirty(stream);
+ if (map->shared_dirty == -1)
+ return -2;
+ map->private_clean = readprivate_clean(stream);
+ if (map->private_clean == -1)
+ return -2;
+ map->private_dirty = readprivate_dirty(stream);
+ if (map->private_dirty == -1)
+ return -2;
+
+ return 0;
+}
+
+static int readsmap(const int pid, struct Totals *totals)
+{
+ FILE *stream;
+ char filename[100];
+
+ snprintf(filename, 100, "/proc/%i/smaps", pid);
+
+ stream = fopen(filename, "r");
+
+ if (stream == 0)
+ return -1;
+
+ totals->size = 0;
+ totals->rss = 0;
+ totals->shared_clean = 0;
+ totals->shared_dirty = 0;
+ totals->private_clean = 0;
+ totals->private_dirty = 0;
+
+ while(!feof(stream))
+ {
+ struct Filemap map;
+ int res;
+ res = readfilemap(stream, &map);
+ if (res == -1)
+ break;
+ if (res == -2)
+ {
+ fprintf(stderr, "ERROR READING %s\n", filename);
+ break;
+ }
+ /*printf("Map: %s\n", map.name);*/
+ totals->size = totals->size + map.size;
+ totals->rss = totals->rss + map.rss;
+ totals->shared_clean = totals->shared_clean + map.shared_clean;
+ totals->shared_dirty = totals->shared_dirty + map.shared_dirty;
+ totals->private_clean = totals->private_clean
+ + map.private_clean;
+ totals->private_dirty = totals->private_dirty
+ + map.private_dirty;
+ }
+
+ fclose(stream);
+
+ /* Read the cmd */
+ totals->cmd[0] = '\0';
+ snprintf(filename, 100, "/proc/%i/cmdline", pid);
+ stream = fopen(filename, "r");
+ fgets(totals->cmd, 200, stream);
+ fclose(stream);
+
+ return 0;
+}
+
+static void showtotals(const int pid, const struct Totals *totals)
+{
+ if (showtitle)
+ printf("PID\tSIZE\tRSS\tS_CLN\tS_DTY\tP_CLN\tP_DTY\tCMD\n");
+ printf("%i\t%i\t%i\t%i\t%i\t%i\t%i\t%s\n",
+ pid,
+ totals->size,
+ totals->rss,
+ totals->shared_clean,
+ totals->shared_dirty,
+ totals->private_clean,
+ totals->private_dirty,
+ totals->cmd);
+}
+
+static void showhelp(const char *progname)
+{
+ fprintf(stderr,"usage: %s <pid>\n", progname);
+}
+
+int main(int argc, char *argv[])
+{
+ int pid;
+ struct Totals t;
+ int res;
+
+ if (argc < 2)
+ {
+ showhelp(argv[0]);
+ return 1;
+ }
+
+ if (argc == 2)
+ pid = atoi(argv[1]);
+ else
+ {
+ if (argv[1][1] == 'q')
+ showtitle = 0;
+ pid = atoi(argv[2]);
+ }
+
+ res = readsmap(pid, &t);
+
+ if (res == -1)
+ return -1;
+
+ showtotals(pid, &t);
+
+ return 0;
+}