diff options
author | Alexander Shishkin <virtuoso@slind.org> | 2010-08-28 23:20:34 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-08-28 23:20:34 +0200 |
commit | 0834a6d3b9daec1f460c3cc836136ace12c53df0 (patch) | |
tree | 5a1ff91bf23113224ee2a54334c020ff97e0f19a /procps | |
parent | 74c992af5c6b8cfe6214e705bc04f8c2f9d8a304 (diff) | |
download | busybox-w32-0834a6d3b9daec1f460c3cc836136ace12c53df0.tar.gz busybox-w32-0834a6d3b9daec1f460c3cc836136ace12c53df0.tar.bz2 busybox-w32-0834a6d3b9daec1f460c3cc836136ace12c53df0.zip |
pmap: new applet. +1k.
pmap is a tool used to look at processes' memory maps, normally found
in procps package. It provides more readable and easily sortable output
(one line per mapping) from maps/smaps files in /proc/PID/. This would
help in debugging memory usage issues, especially on devices where lots
of typing is not a viable option.
This patch does'n implement -d and -A command line options of GNU pmap,
since those are not that must have features and I was afraid of going
blind from looking at its code.
The implementation takes smaps scanning part out of procps_scan() function
and moves it into procps_read_smaps(), which does more detailed processing
of a single PID's smaps data.
Signed-off-by: Alexander Shishkin <virtuoso@slind.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'procps')
-rw-r--r-- | procps/pmap.c | 111 | ||||
-rw-r--r-- | procps/top.c | 16 |
2 files changed, 119 insertions, 8 deletions
diff --git a/procps/pmap.c b/procps/pmap.c new file mode 100644 index 000000000..cfa94ed82 --- /dev/null +++ b/procps/pmap.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * pmap implementation for busybox | ||
3 | * | ||
4 | * Copyright (C) 2010 Nokia Corporation. All rights reserved. | ||
5 | * Written by Alexander Shishkin <virtuoso@slind.org> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see the LICENSE file in this source tree | ||
8 | * for details. | ||
9 | */ | ||
10 | |||
11 | //applet:IF_PMAP(APPLET(pmap, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
12 | //kbuild:lib-$(CONFIG_PMAP) += pmap.o | ||
13 | |||
14 | //config:config PMAP | ||
15 | //config: bool "pmap" | ||
16 | //config: default y | ||
17 | //config: help | ||
18 | //config: Display processes' memory mappings. | ||
19 | |||
20 | //usage:#define pmap_trivial_usage | ||
21 | //usage: "[-x][-q] PID" | ||
22 | //usage:#define pmap_full_usage "\n\n" | ||
23 | //usage: "Display detailed precesses' memory usage\n" | ||
24 | //usage: "\nOptions:" | ||
25 | //usage: "\n -x show details" | ||
26 | //usage: "\n -q quiet" | ||
27 | |||
28 | #include "libbb.h" | ||
29 | |||
30 | #if ULONG_MAX == 0xffffffff | ||
31 | # define TABS "\t" | ||
32 | # define AFMT "8" | ||
33 | # define DASHES "" | ||
34 | #else | ||
35 | # define TABS "\t\t" | ||
36 | # define AFMT "16" | ||
37 | # define DASHES "--------" | ||
38 | #endif | ||
39 | |||
40 | enum { | ||
41 | OPT_x = 1 << 0, | ||
42 | OPT_q = 1 << 1, | ||
43 | }; | ||
44 | |||
45 | static void print_smaprec(struct smaprec *currec, void *data) | ||
46 | { | ||
47 | unsigned opt = (unsigned)data; | ||
48 | |||
49 | printf("%0" AFMT "lx ", currec->smap_start); | ||
50 | |||
51 | if (opt & OPT_x) | ||
52 | printf("%7lu %7lu %7lu %7lu ", | ||
53 | currec->smap_size, | ||
54 | currec->smap_pss, | ||
55 | currec->private_dirty, | ||
56 | currec->smap_swap); | ||
57 | else | ||
58 | printf("%7luK", currec->smap_size); | ||
59 | |||
60 | printf(" %.4s %s\n", currec->smap_mode, currec->smap_name); | ||
61 | } | ||
62 | |||
63 | static int procps_get_maps(pid_t pid, unsigned opt) | ||
64 | { | ||
65 | struct smaprec total; | ||
66 | int ret; | ||
67 | char buf[256]; | ||
68 | |||
69 | read_cmdline(buf, sizeof(buf), pid, "no such process"); | ||
70 | printf("%u: %s\n", (int)pid, buf); | ||
71 | |||
72 | if (!(opt & OPT_q) && (opt & OPT_x)) | ||
73 | puts("Address" TABS " Kbytes PSS Dirty Swap Mode Mapping"); | ||
74 | |||
75 | memset(&total, 0, sizeof(total)); | ||
76 | |||
77 | ret = procps_read_smaps(pid, &total, print_smaprec, (void*)opt); | ||
78 | if (ret) | ||
79 | return ret; | ||
80 | |||
81 | if (!(opt & OPT_q)) { | ||
82 | if (opt & OPT_x) | ||
83 | printf("--------" DASHES " ------ ------ ------ ------\n" | ||
84 | "total" TABS " %7lu %7lu %7lu %7lu\n", | ||
85 | total.smap_size, total.smap_pss, total.private_dirty, total.smap_swap); | ||
86 | else | ||
87 | printf("mapped: %luK\n", total.smap_size); | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | int pmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
94 | int pmap_main(int argc UNUSED_PARAM, char **argv) | ||
95 | { | ||
96 | unsigned opts; | ||
97 | int ret; | ||
98 | |||
99 | opts = getopt32(argv, "xq"); | ||
100 | argv += optind; | ||
101 | |||
102 | ret = 0; | ||
103 | while (*argv) { | ||
104 | pid_t pid = xatoi_positive(*argv++); | ||
105 | /* GNU pmap returns 42 if any of the pids failed */ | ||
106 | if (procps_get_maps(pid, opts) != 0) | ||
107 | ret = 42; | ||
108 | } | ||
109 | |||
110 | return ret; | ||
111 | } | ||
diff --git a/procps/top.c b/procps/top.c index fd758099e..4f37878de 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -942,20 +942,20 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
942 | } | 942 | } |
943 | #if ENABLE_FEATURE_TOPMEM | 943 | #if ENABLE_FEATURE_TOPMEM |
944 | else { /* TOPMEM */ | 944 | else { /* TOPMEM */ |
945 | if (!(p->mapped_ro | p->mapped_rw)) | 945 | if (!(p->smaps.mapped_ro | p->smaps.mapped_rw)) |
946 | continue; /* kernel threads are ignored */ | 946 | continue; /* kernel threads are ignored */ |
947 | n = ntop; | 947 | n = ntop; |
948 | /* No bug here - top and topmem are the same */ | 948 | /* No bug here - top and topmem are the same */ |
949 | top = xrealloc_vector(topmem, 6, ntop++); | 949 | top = xrealloc_vector(topmem, 6, ntop++); |
950 | strcpy(topmem[n].comm, p->comm); | 950 | strcpy(topmem[n].comm, p->comm); |
951 | topmem[n].pid = p->pid; | 951 | topmem[n].pid = p->pid; |
952 | topmem[n].vsz = p->mapped_rw + p->mapped_ro; | 952 | topmem[n].vsz = p->smaps.mapped_rw + p->smaps.mapped_ro; |
953 | topmem[n].vszrw = p->mapped_rw; | 953 | topmem[n].vszrw = p->smaps.mapped_rw; |
954 | topmem[n].rss_sh = p->shared_clean + p->shared_dirty; | 954 | topmem[n].rss_sh = p->smaps.shared_clean + p->smaps.shared_dirty; |
955 | topmem[n].rss = p->private_clean + p->private_dirty + topmem[n].rss_sh; | 955 | topmem[n].rss = p->smaps.private_clean + p->smaps.private_dirty + topmem[n].rss_sh; |
956 | topmem[n].dirty = p->private_dirty + p->shared_dirty; | 956 | topmem[n].dirty = p->smaps.private_dirty + p->smaps.shared_dirty; |
957 | topmem[n].dirty_sh = p->shared_dirty; | 957 | topmem[n].dirty_sh = p->smaps.shared_dirty; |
958 | topmem[n].stack = p->stack; | 958 | topmem[n].stack = p->smaps.stack; |
959 | } | 959 | } |
960 | #endif | 960 | #endif |
961 | } /* end of "while we read /proc" */ | 961 | } /* end of "while we read /proc" */ |