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/pmap.c | |
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/pmap.c')
-rw-r--r-- | procps/pmap.c | 111 |
1 files changed, 111 insertions, 0 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 | } | ||