smapsum.c
changeset 0 5425a5439bcd
equal deleted inserted replaced
-1:000000000000 0:5425a5439bcd
       
     1 #include <stdio.h>
       
     2 #include <string.h>
       
     3 #include <stdlib.h>
       
     4 
       
     5 static char showtitle = 1;
       
     6 
       
     7 struct Filemap
       
     8 {
       
     9 	char name[300];
       
    10 	int size;
       
    11 	int rss;
       
    12 	int shared_clean;
       
    13 	int shared_dirty;
       
    14 	int private_clean;
       
    15 	int private_dirty;
       
    16 	enum {
       
    17 		PRIVATE,
       
    18 		SHARED
       
    19 	} type;
       
    20 	char readable;
       
    21 	char writable;
       
    22 	char executable;
       
    23 	int inode;
       
    24 	struct {
       
    25 		unsigned char major;
       
    26 		unsigned char minor;
       
    27 	} device;
       
    28 };
       
    29 
       
    30 struct Totals
       
    31 {
       
    32 	int size;
       
    33 	int rss;
       
    34 	int shared_clean;
       
    35 	int shared_dirty;
       
    36 	int private_clean;
       
    37 	int private_dirty;
       
    38 	char cmd[200];
       
    39 };
       
    40 
       
    41 
       
    42 static int readkb(const char *field, FILE *stream)
       
    43 {
       
    44 	int kb;
       
    45 	int res;
       
    46 	char line[200];
       
    47 
       
    48 	strcpy(line, field);
       
    49 	strcat(line, " %i kB\n");
       
    50 	res = fscanf(stream, line, &kb);
       
    51 	if (res != 1)
       
    52 		return -1;
       
    53 	return kb;
       
    54 }
       
    55 
       
    56 static int readsize(FILE *stream)
       
    57 {
       
    58 	return readkb("Size:", stream);
       
    59 }
       
    60 
       
    61 static int readrss(FILE *stream)
       
    62 {
       
    63 	return readkb("Rss:", stream);
       
    64 }
       
    65 
       
    66 static int readshared_clean(FILE *stream)
       
    67 {
       
    68 	return readkb("Shared_Clean:", stream);
       
    69 }
       
    70 
       
    71 static int readshared_dirty(FILE *stream)
       
    72 {
       
    73 	return readkb("Shared_Dirty:", stream);
       
    74 }
       
    75 
       
    76 static int readprivate_clean(FILE *stream)
       
    77 {
       
    78 	return readkb("Private_Clean:", stream);
       
    79 }
       
    80 
       
    81 static int readprivate_dirty(FILE *stream)
       
    82 {
       
    83 	return readkb("Private_Dirty:", stream);
       
    84 }
       
    85 
       
    86 static int readfilemap(FILE *stream, struct Filemap *map)
       
    87 {
       
    88 	int res;
       
    89 	char type;
       
    90 
       
    91 	unsigned int major;
       
    92 	unsigned int minor;
       
    93 
       
    94 	res = fscanf(stream, "%*x-%*x %c%c%c%c %*x %x:%x %i",
       
    95 			&map->readable,
       
    96 			&map->writable,
       
    97 			&map->executable,
       
    98 			&type,
       
    99 			&major,
       
   100 			&minor,
       
   101 			&map->inode);
       
   102 
       
   103 	if (res != 7)
       
   104 		return -1;
       
   105 
       
   106 	fgets(map->name, 300, stream);
       
   107 
       
   108 	map->device.major = major;
       
   109 	map->device.minor = minor;
       
   110 
       
   111 	if (type == 's')
       
   112 		map->type = PRIVATE;
       
   113 	else
       
   114 		map->type = SHARED;
       
   115 
       
   116 	if (map->readable == '-')
       
   117 		map->readable = 0;
       
   118 	if (map->writable == '-')
       
   119 		map->writable = 0;
       
   120 	if (map->executable == '-')
       
   121 		map->executable = 0;
       
   122 
       
   123 	map->size = readsize(stream);
       
   124 	if (map->size == -1)
       
   125 		return -2;
       
   126 	map->rss = readrss(stream);
       
   127 	if (map->rss == -1)
       
   128 		return -2;
       
   129 	map->shared_clean = readshared_clean(stream);
       
   130 	if (map->shared_clean == -1)
       
   131 		return -2;
       
   132 	map->shared_dirty = readshared_dirty(stream);
       
   133 	if (map->shared_dirty == -1)
       
   134 		return -2;
       
   135 	map->private_clean = readprivate_clean(stream);
       
   136 	if (map->private_clean == -1)
       
   137 		return -2;
       
   138 	map->private_dirty = readprivate_dirty(stream);
       
   139 	if (map->private_dirty == -1)
       
   140 		return -2;
       
   141 
       
   142 	return 0;
       
   143 }
       
   144 
       
   145 static int readsmap(const int pid, struct Totals *totals)
       
   146 {
       
   147 	FILE *stream;
       
   148 	char filename[100];
       
   149 
       
   150 	snprintf(filename, 100, "/proc/%i/smaps", pid);
       
   151 
       
   152 	stream = fopen(filename, "r");
       
   153 
       
   154 	if (stream == 0)
       
   155 		return -1;
       
   156 
       
   157 	totals->size = 0;
       
   158 	totals->rss = 0;
       
   159 	totals->shared_clean = 0;
       
   160 	totals->shared_dirty = 0;
       
   161 	totals->private_clean = 0;
       
   162 	totals->private_dirty = 0;
       
   163 
       
   164 	while(!feof(stream))
       
   165 	{
       
   166 		struct Filemap map;
       
   167 		int res;
       
   168 		res = readfilemap(stream, &map);
       
   169 		if (res == -1)
       
   170 			break;
       
   171 		if (res == -2)
       
   172 		{
       
   173 			fprintf(stderr, "ERROR READING %s\n", filename);
       
   174 			break;
       
   175 		}
       
   176 		/*printf("Map: %s\n", map.name);*/
       
   177 		totals->size = totals->size + map.size;
       
   178 		totals->rss = totals->rss + map.rss;
       
   179 		totals->shared_clean = totals->shared_clean + map.shared_clean;
       
   180 		totals->shared_dirty = totals->shared_dirty + map.shared_dirty;
       
   181 		totals->private_clean = totals->private_clean
       
   182 			+ map.private_clean;
       
   183 		totals->private_dirty = totals->private_dirty
       
   184 			+ map.private_dirty;
       
   185 	}
       
   186 
       
   187 	fclose(stream);
       
   188 
       
   189 	/* Read the cmd */
       
   190 	totals->cmd[0] = '\0';
       
   191 	snprintf(filename, 100, "/proc/%i/cmdline", pid);
       
   192 	stream = fopen(filename, "r");
       
   193 	fgets(totals->cmd, 200, stream);
       
   194 	fclose(stream);
       
   195 
       
   196 	return 0;
       
   197 }
       
   198 
       
   199 static void showtotals(const int pid, const struct Totals *totals)
       
   200 {
       
   201 	if (showtitle)
       
   202 		printf("PID\tSIZE\tRSS\tS_CLN\tS_DTY\tP_CLN\tP_DTY\tCMD\n");
       
   203 	printf("%i\t%i\t%i\t%i\t%i\t%i\t%i\t%s\n",
       
   204 			pid,
       
   205 			totals->size,
       
   206 			totals->rss,
       
   207 			totals->shared_clean,
       
   208 			totals->shared_dirty,
       
   209 			totals->private_clean,
       
   210 			totals->private_dirty,
       
   211 			totals->cmd);
       
   212 }
       
   213 
       
   214 static void showhelp(const char *progname)
       
   215 {
       
   216 	fprintf(stderr,"usage: %s <pid>\n", progname);
       
   217 }
       
   218 
       
   219 int main(int argc, char *argv[])
       
   220 {
       
   221 	int pid;
       
   222 	struct Totals t;
       
   223 	int res;
       
   224 
       
   225 	if (argc < 2)
       
   226 	{
       
   227 		showhelp(argv[0]);
       
   228 		return 1;
       
   229 	}
       
   230 
       
   231 	if (argc == 2)
       
   232 		pid = atoi(argv[1]);
       
   233 	else
       
   234 	{
       
   235 		if (argv[1][1] == 'q')
       
   236 			showtitle = 0;
       
   237 		pid = atoi(argv[2]);
       
   238 	}
       
   239 
       
   240 	res = readsmap(pid, &t);
       
   241 
       
   242 	if (res == -1)
       
   243 		return -1;
       
   244 
       
   245 	showtotals(pid, &t);
       
   246 
       
   247 	return 0;
       
   248 }