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>
This commit is contained in:
		
				
					committed by
					
						
						Denys Vlasenko
					
				
			
			
				
	
			
			
			
						parent
						
							74c992af5c
						
					
				
				
					commit
					0834a6d3b9
				
			
							
								
								
									
										111
									
								
								procps/pmap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								procps/pmap.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
/*
 | 
			
		||||
 * pmap implementation for busybox
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
 | 
			
		||||
 * Written by Alexander Shishkin <virtuoso@slind.org>
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under GPLv2 or later, see the LICENSE file in this source tree
 | 
			
		||||
 * for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//applet:IF_PMAP(APPLET(pmap, _BB_DIR_USR_BIN, _BB_SUID_DROP))
 | 
			
		||||
//kbuild:lib-$(CONFIG_PMAP)     += pmap.o
 | 
			
		||||
 | 
			
		||||
//config:config PMAP
 | 
			
		||||
//config:       bool "pmap"
 | 
			
		||||
//config:       default y
 | 
			
		||||
//config:       help
 | 
			
		||||
//config:         Display processes' memory mappings.
 | 
			
		||||
 | 
			
		||||
//usage:#define pmap_trivial_usage
 | 
			
		||||
//usage:       "[-x][-q] PID"
 | 
			
		||||
//usage:#define pmap_full_usage "\n\n"
 | 
			
		||||
//usage:       "Display detailed precesses' memory usage\n"
 | 
			
		||||
//usage:       "\nOptions:"
 | 
			
		||||
//usage:       "\n     -x              show details"
 | 
			
		||||
//usage:       "\n     -q              quiet"
 | 
			
		||||
 | 
			
		||||
#include "libbb.h"
 | 
			
		||||
 | 
			
		||||
#if ULONG_MAX == 0xffffffff
 | 
			
		||||
# define TABS "\t"
 | 
			
		||||
# define AFMT "8"
 | 
			
		||||
# define DASHES ""
 | 
			
		||||
#else
 | 
			
		||||
# define TABS "\t\t"
 | 
			
		||||
# define AFMT "16"
 | 
			
		||||
# define DASHES "--------"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	OPT_x = 1 << 0,
 | 
			
		||||
	OPT_q = 1 << 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void print_smaprec(struct smaprec *currec, void *data)
 | 
			
		||||
{
 | 
			
		||||
	unsigned opt = (unsigned)data;
 | 
			
		||||
 | 
			
		||||
	printf("%0" AFMT "lx ", currec->smap_start);
 | 
			
		||||
 | 
			
		||||
	if (opt & OPT_x)
 | 
			
		||||
		printf("%7lu %7lu %7lu %7lu ",
 | 
			
		||||
			currec->smap_size,
 | 
			
		||||
			currec->smap_pss,
 | 
			
		||||
			currec->private_dirty,
 | 
			
		||||
			currec->smap_swap);
 | 
			
		||||
	else
 | 
			
		||||
		printf("%7luK", currec->smap_size);
 | 
			
		||||
 | 
			
		||||
	printf(" %.4s  %s\n", currec->smap_mode, currec->smap_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int procps_get_maps(pid_t pid, unsigned opt)
 | 
			
		||||
{
 | 
			
		||||
	struct smaprec total;
 | 
			
		||||
	int ret;
 | 
			
		||||
	char buf[256];
 | 
			
		||||
 | 
			
		||||
	read_cmdline(buf, sizeof(buf), pid, "no such process");
 | 
			
		||||
	printf("%u: %s\n", (int)pid, buf);
 | 
			
		||||
 | 
			
		||||
	if (!(opt & OPT_q) && (opt & OPT_x))
 | 
			
		||||
		puts("Address" TABS "  Kbytes     PSS   Dirty    Swap  Mode  Mapping");
 | 
			
		||||
 | 
			
		||||
	memset(&total, 0, sizeof(total));
 | 
			
		||||
 | 
			
		||||
	ret = procps_read_smaps(pid, &total, print_smaprec, (void*)opt);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	if (!(opt & OPT_q)) {
 | 
			
		||||
		if (opt & OPT_x)
 | 
			
		||||
			printf("--------" DASHES "  ------  ------  ------  ------\n"
 | 
			
		||||
				"total" TABS " %7lu %7lu %7lu %7lu\n",
 | 
			
		||||
				total.smap_size, total.smap_pss, total.private_dirty, total.smap_swap);
 | 
			
		||||
		else
 | 
			
		||||
			printf("mapped: %luK\n", total.smap_size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 | 
			
		||||
int pmap_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	unsigned opts;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	opts = getopt32(argv, "xq");
 | 
			
		||||
	argv += optind;
 | 
			
		||||
 | 
			
		||||
	ret = 0;
 | 
			
		||||
	while (*argv) {
 | 
			
		||||
		pid_t pid = xatoi_positive(*argv++);
 | 
			
		||||
		/* GNU pmap returns 42 if any of the pids failed */
 | 
			
		||||
		if (procps_get_maps(pid, opts) != 0)
 | 
			
		||||
			ret = 42;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user