procrank.c revision e16cb84e2324f05334d18dcf5956f20f44262b62
1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/* 2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * you may not use this file except in compliance with the License. 6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * You may obtain a copy of the License at 7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * See the License for the specific language governing permissions and 14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * limitations under the License. 15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */ 16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <dirent.h> 18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <errno.h> 19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h> 20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/types.h> 21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h> 22e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 23e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <pagemap/pagemap.h> 24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct proc_info { 26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pid_t pid; 27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_memusage_t usage; 28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project unsigned long wss; 29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}; 30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(char *myname); 32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int getprocname(pid_t pid, char *buf, size_t len); 33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(long long a, long long b); 34e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define declare_sort(field) \ 36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project static int sort_by_ ## field (const void *a, const void *b) 37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(vss); 39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(rss); 40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(pss); 41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(uss); 42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint (*compfn)(const void *a, const void *b); 44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int order; 45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 46e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_PROCS 256 47e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 48e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char *argv[]) { 49e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_kernel_t *ker; 50e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_process_t *proc; 51e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pid_t *pids; 52e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct proc_info *procs[MAX_PROCS]; 53e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project size_t num_procs; 54e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project char cmdline[256]; 55e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int error; 56e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 57e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project #define WS_OFF 0 58e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project #define WS_ONLY 1 59e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project #define WS_RESET 2 60e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int ws; 61e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 62e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int i, j; 63e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 64e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project compfn = &sort_by_pss; 65e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project order = -1; 66e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ws = WS_OFF; 67e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 68e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 1; i < argc; i++) { 69e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-v")) { compfn = &sort_by_vss; continue; } 70e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-r")) { compfn = &sort_by_rss; continue; } 71e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-p")) { compfn = &sort_by_pss; continue; } 72e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-u")) { compfn = &sort_by_uss; continue; } 73e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-w")) { ws = WS_ONLY; continue; } 74e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-W")) { ws = WS_RESET; continue; } 75e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-R")) { order *= -1; continue; } 76e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-h")) { usage(argv[0]); exit(0); } 77e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Invalid argument \"%s\".\n", argv[i]); 78e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project usage(argv[0]); 79e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 80e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 81e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 82e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = pm_kernel_create(&ker); 83e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (error) { 84e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Error creating kernel interface -- " 85e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project "does this kernel have pagemap?\n"); 86e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 87e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 88e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 89e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = pm_kernel_pids(ker, &pids, &num_procs); 90e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (error) { 91e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Error listing processes.\n"); 92e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 93e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 94e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 95e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < num_procs; i++) { 96e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i] = malloc(sizeof(struct proc_info)); 97e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!procs[i]) { 98e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "malloc: %s\n", strerror(errno)); 99e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 100e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 101e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->pid = pids[i]; 102e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = pm_process_create(ker, pids[i], &proc); 103e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!error) { 104e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project switch (ws) { 105e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project case WS_OFF: 106e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_process_usage(proc, &procs[i]->usage); 107e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project break; 108e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project case WS_ONLY: 109e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_process_workingset(proc, &procs[i]->usage, 0); 110e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project break; 111e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project case WS_RESET: 112e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_process_workingset(proc, NULL, 1); 113e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project break; 114e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 115e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_process_destroy(proc); 116e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 117e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "warning: could not create process interface for %d\n", pids[i]); 118e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_memusage_zero(&procs[i]->usage); 119e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 120e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 121e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 122e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(pids); 123e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 124e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ws == WS_RESET) exit(0); 125e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 126e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project j = 0; 127e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < num_procs; i++) { 128e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (procs[i]->usage.vss) 129e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[j++] = procs[i]; 130e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 131e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project num_procs = j; 132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 133e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project qsort(procs, num_procs, sizeof(procs[0]), compfn); 134e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 135e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ws) 136e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5s %7s %7s %7s %s\n", "PID", "WRss", "WPss", "WUss", "cmdline"); 137e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project else 138e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5s %7s %7s %7s %7s %s\n", "PID", "Vss", "Rss", "Pss", "Uss", "cmdline"); 139e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < num_procs; i++) { 140e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project getprocname(procs[i]->pid, cmdline, sizeof(cmdline)); 141e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ws) 142e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5d %6dK %6dK %6dK %s\n", 143e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->pid, 144e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.rss / 1024, 145e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.pss / 1024, 146e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.uss / 1024, 147e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project cmdline 148e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ); 149e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project else 150e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5d %6dK %6dK %6dK %6dK %s\n", 151e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->pid, 152e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.vss / 1024, 153e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.rss / 1024, 154e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.pss / 1024, 155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.uss / 1024, 156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project cmdline 157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ); 158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 159e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 160e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 161e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 163e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(char *myname) { 164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Usage: %s [ -W ] [ -v | -r | -p | -u | -h ]\n" 165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -v Sort by VSS.\n" 166e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -r Sort by RSS.\n" 167e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -p Sort by PSS.\n" 168e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -u Sort by USS.\n" 169e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " (Default sort order is PSS.)\n" 170e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -R Reverse sort order (default is descending).\n" 171e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -w Display statistics for working set only.\n" 172e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -W Reset working set of all processes.\n" 173e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -h Display this help screen.\n", 174e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project myname); 175e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 177e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int getprocname(pid_t pid, char *buf, size_t len) { 178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project char filename[20]; 179e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project FILE *f; 180e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 181e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project sprintf(filename, "/proc/%d/cmdline", pid); 182e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project f = fopen(filename, "r"); 183e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!f) { *buf = '\0'; return 1; } 184e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!fgets(buf, len, f)) { *buf = '\0'; return 2; } 185e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fclose(f); 186e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 187e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 188e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 189e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(long long a, long long b) { 190e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (a < b) return -1; 191e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (a > b) return 1; 192e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 193e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 194e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 195e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define create_sort(field, compfn) \ 196e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project static int sort_by_ ## field (const void *a, const void *b) { \ 197e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return order * compfn( \ 198e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project (*((struct proc_info**)a))->usage.field, \ 199e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project (*((struct proc_info**)b))->usage.field \ 200e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ); \ 201e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 202e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 203e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(vss, numcmp) 204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(rss, numcmp) 205e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(pss, numcmp) 206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(uss, numcmp) 207