changeset 1030:9686469a857a

Rewrite pmap to be simpler and match other implementation's output more closely.
author Rob Landley <rob@landley.net>
date Tue, 27 Aug 2013 23:48:54 -0500
parents b59f4b87b9ec
children 0d0c01ac5c63
files lib/lib.c toys/other/pmap.c toys/pending/pmap.c
diffstat 3 files changed, 113 insertions(+), 128 deletions(-) [+]
line wrap: on
line diff
--- a/lib/lib.c	Tue Aug 27 03:31:27 2013 -0500
+++ b/lib/lib.c	Tue Aug 27 23:48:54 2013 -0500
@@ -325,6 +325,8 @@
   fd = open(name, O_RDONLY);
   if (fd == -1) return 0;
   len = fdlength(fd);
+  // proc files don't report a length, so try 1 page minimum.
+  if (len<4096) len = 4095;
   buf = xmalloc(len+1);
   buf[readall(fd, buf, len)] = 0;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/pmap.c	Tue Aug 27 23:48:54 2013 -0500
@@ -0,0 +1,111 @@
+/* pmap.c - Reports the memory map of a process or processes.
+ *
+ * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com>
+ * Copyright 2013 Kyungwan Han <asura321@gmail.com>
+ *
+ * No Standard.
+
+USE_PMAP(NEWTOY(pmap, "<1xq", TOYFLAG_BIN))
+
+config PMAP
+  bool "pmap"
+  default y
+  help
+    usage: pmap [-xq] [pids...]
+
+    Reports the memory map of a process or processes.
+
+    -x Show the extended format.
+    -q Do not display some header/footer lines.
+*/
+
+#define FOR_pmap
+#include "toys.h"
+
+void pmap_main(void)
+{
+  while (*toys.optargs) {
+    pid_t pid = atolx(*toys.optargs++);
+    FILE *fp;
+    char *line, *oldline = 0, *name = 0,
+         *k = (toys.optflags & FLAG_x) ? "" : "K";
+    size_t len;
+    long long start, end, pss, tpss = 0, dirty, tdirty = 0, swap, tswap = 0,
+              total = 0;
+    int count, xx = 0;
+
+    snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid);
+    line = readfile(toybuf);
+    if (!line) error_msg("No %lu", (long)pid);
+    xprintf("%u: %s\n", (int)pid, line);
+    free(line);
+
+    // Header
+    // Only use the more verbose file in -x mode
+    sprintf(toybuf, "/proc/%u/%smaps", pid,
+      (toys.optflags & FLAG_x) ? "s" : "");
+    if (!(fp = fopen(toybuf, "r"))) {
+      error_msg("No %ld\n", (long)pid);
+      return;
+    }
+
+    if ((toys.optflags & (FLAG_q|FLAG_x)) == FLAG_x)
+      xprintf("Address%*cKbytes     PSS   Dirty    Swap  Mode  Mapping\n",
+        (sizeof(long)*2)-4, ' ');
+
+    // Loop through mappings
+    for (;;) {
+      int off;
+
+      line = 0;
+      if (0 >= getline(&line, &len, fp)) break;
+      count = sscanf(line, "%llx-%llx %s %*s %*s %*s %n",
+        &start, &end, toybuf, &off);
+
+      if (count == 3) {
+        name = line[off] ? line+off : "  [anon]\n";
+        if (toybuf[3] == 'p') toybuf[3] = '-';
+        total += end = (end-start)/1024;
+        printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start,
+          6+!!(toys.optflags & FLAG_x), end, k);
+        if (toys.optflags & FLAG_x) {
+          oldline = line;
+          continue;
+        }
+      } else {
+        if (0<sscanf(line, "Pss: %lld", &pss)
+            || 0<sscanf(line, "Private_Dirty: %lld", &dirty)
+            || 0<sscanf(line, "Swap: %lld", &swap)) xx++;
+        free(line);
+        if (xx<3) continue;
+        line = oldline;
+        name = basename(name);
+        xx = 0;
+        printf("% 7lld %7lld %7lld ", pss, dirty, swap);
+        tpss += pss;
+        tdirty += dirty;
+        tswap += swap;
+      }
+
+      xprintf("%s-  %s%s", toybuf, line[off]=='[' ? "  " : "", name);
+
+      free(line);
+      line = 0;
+    }
+
+    // Trailer
+    if (!(toys.optflags & FLAG_q)) {
+      int x = !!(toys.optflags & FLAG_x);
+      if (x) {
+        memset(toybuf, '-', 16);
+        xprintf("%.*s  ------  ------  ------  ------\n", (int)(sizeof(long)*2),
+          toybuf);
+      }
+      printf("total% *lld%s", 2*(int)(sizeof(long)+1)+x, total, k);
+      if (x) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap);
+      xputc('\n');
+    }
+ 
+    fclose(fp);
+  }
+}
--- a/toys/pending/pmap.c	Tue Aug 27 03:31:27 2013 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/* pmap.c - Reports the memory map of a process or processes.
- *
- * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com>
- * Copyright 2013 Kyungwan Han <asura321@gmail.com>
- *
- * No Standard.
- *
-USE_PMAP(NEWTOY(pmap, "xq", TOYFLAG_BIN))
-
-config PMAP
-  bool "pmap"
-  default y
-  help
-    usage: pmap [-xq] [pids...]
-
-    Reports the memory map of a process or processes.
-
-    -x Show the extended format.
-    -q Do not display some header/footer lines.
-*/
-#define FOR_pmap
-#include "toys.h"
-
-#if ULONG_MAX == 0xffffffff
- # define TAB "\t"
- # define WIDTH "8"
- # define DASHES ""
-#else
- # define TAB "\t\t"
- # define WIDTH "16"
- # define DASHES "--------"
-#endif
-
-struct _smaps {
-  unsigned long start_addr, size, pss, pdirty, swap;
-  char mode[5], *mapping;
-};
-
-//Display mapping info.
-static void show_maps(struct _smaps *map)
-{
-  xprintf("%0" WIDTH "lx ", map->start_addr);
-  if (toys.optflags & FLAG_x)
-    xprintf("%7lu %7lu %7lu %7lu ", map->size, map->pss, map->pdirty, map->swap);
-  else xprintf("%7luK", map->size);
-  xprintf(" %.4s  \n", map->mode, map->mapping);
-  free(map->mapping);
-}
-
-//Read "/proc/pid/smaps" file and extract data.
-static int read_smaps(pid_t pid, struct _smaps *total)
-{
-  struct _smaps curmap;
-  char *line;
-  int fd, nitems;
-  
-  snprintf(toybuf, sizeof(toybuf), "/proc/%u/smaps", pid);
-  if ((fd = open(toybuf, O_RDONLY)) < 0) return fd;
-  memset(&curmap, 0, sizeof(struct _smaps)); 
-  while ((line = get_line(fd))) {
-    char *ptr = NULL;
-    *toybuf = *(toybuf+34) = *(toybuf+40) = '\0';
-    //1st line format -> start_addr-End_addr rw-s ADR M:m OFS
-    if ((ptr = strchr(line, '-'))) {
-      if (curmap.size) show_maps(&curmap);
-      memset(&curmap, 0, sizeof(struct _smaps));
-      nitems = sscanf(line, "%s %s %*s %*s %*s %s\n", toybuf, toybuf+34, toybuf+40);
-      if (nitems >= 2) {
-        ptr = strchr(toybuf, '-');
-        *ptr = '\0';
-        total->size += curmap.size = (strtoul(++ptr, NULL, 16) - 
-            (curmap.start_addr = strtoul(toybuf, NULL, 16))) >> 10;
-        strncpy(curmap.mode, toybuf+34, sizeof(curmap.mode)-1);
-        if (!*(toybuf+40)) curmap.mapping = xstrdup("  [ anon ]");
-        else curmap.mapping = xstrdup(toybuf+40);
-      }
-    } else { //2nd line onwards..
-      unsigned long val = 0;
-      nitems = sscanf(line, "%s %lu\n", toybuf, &val);
-      if (nitems == 2) {
-        if (!strcmp("Pss:", toybuf)) total->pss += (curmap.pss = val);
-        else if (!strcmp("Private_Dirty:", toybuf)) total->pdirty += (curmap.pdirty = val);
-        else if (!strcmp("Swap:", toybuf)) total->swap += (curmap.swap = val);
-      }
-    }
-    free(line);
-  }
-  if (curmap.size) show_maps(&curmap);
-  xclose(fd);
-  return 0;
-}
-
-void pmap_main(void)
-{
-  struct _smaps total;
-  int fd;
-  
-  while (*toys.optargs) {
-    pid_t pid = get_int_value(*toys.optargs++, 0, INT_MAX);
-    snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid);
-    if ((fd = open(toybuf, O_RDONLY)) == -1) xprintf("%u: [no such process]\n", pid);
-    else {
-      ssize_t len = readall(fd, toybuf, sizeof(toybuf) -1);
-      if (len <= 0) xprintf("%u: [no such process]\n", (int)pid);
-      else {
-        toybuf[len] = '\0';
-        while (--len >= 0 && toybuf[len] == '\0') continue;
-        for (; len > 0; len--)
-          if ((unsigned char)toybuf[len] < ' ') toybuf[len] = ' ';
-        xprintf("%u: %s\n", (int)pid, toybuf);
-      }
-      xclose(fd);
-    }
-    if (!(toys.optflags & FLAG_q) && (toys.optflags & FLAG_x))
-      xprintf("Address" TAB "  Kbytes     PSS   Dirty    Swap  Mode  Mapping\n");
-
-    memset(&total, 0, sizeof(struct _smaps));
-    if (read_smaps(pid, &total)) toys.exitval = 42;
-    else { //to display total mapping.
-      if (!(toys.optflags & FLAG_q) )
-        (toys.optflags & FLAG_x)
-          ? xprintf("--------" DASHES "  ------  ------  ------  ------\n"
-              "total" TAB " %7lu %7lu %7lu %7lu\n",
-              total.size, total.pss, total.pdirty, total.swap)
-          : xprintf("mapped: %luK\n", total.size);
-    }
-  }
-}