procrank.c revision 83b0b0a57a0c20984e207e4d6987faeba736140c
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> 22b56034796a7cadee89c4cd5e3c0f0730193231deOlivier Bailly#include <string.h> 23e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn#include <fcntl.h> 24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <pagemap/pagemap.h> 26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct proc_info { 28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pid_t pid; 29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_memusage_t usage; 30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project unsigned long wss; 31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}; 32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(char *myname); 3416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootstatic int getprocname(pid_t pid, char *buf, int len); 35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(long long a, long long b); 36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define declare_sort(field) \ 38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project static int sort_by_ ## field (const void *a, const void *b) 39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(vss); 41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(rss); 42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(pss); 43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(uss); 44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint (*compfn)(const void *a, const void *b); 46e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int order; 47e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 48e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackbornvoid print_mem_info() { 4983b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn char buffer[1024]; 50e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn int numFound = 0; 51e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 52e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn int fd = open("/proc/meminfo", O_RDONLY); 53e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 54e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn if (fd < 0) { 55e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn printf("Unable to open /proc/meminfo: %s\n", strerror(errno)); 56e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn return; 57e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } 58e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 59e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn const int len = read(fd, buffer, sizeof(buffer)-1); 60e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn close(fd); 61e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 62e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn if (len < 0) { 63e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn printf("Empty /proc/meminfo"); 64e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn return; 65e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } 66e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn buffer[len] = 0; 67e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 68e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn static const char* const tags[] = { 69e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "MemTotal:", 70e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "MemFree:", 71e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "Buffers:", 72e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "Cached:", 7383b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn "Shmem:", 7483b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn "Slab:", 75e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn NULL 76e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn }; 77e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn static const int tagsLen[] = { 78e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 9, 79e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 8, 80e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 8, 81e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 7, 8283b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn 6, 8383b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn 5, 84e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 0 85e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn }; 8683b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn long mem[] = { 0, 0, 0, 0, 0, 0 }; 87e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 88e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn char* p = buffer; 8983b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn while (*p && numFound < 6) { 90e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn int i = 0; 91e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn while (tags[i]) { 92e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn if (strncmp(p, tags[i], tagsLen[i]) == 0) { 93e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn p += tagsLen[i]; 94e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn while (*p == ' ') p++; 95e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn char* num = p; 96e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn while (*p >= '0' && *p <= '9') p++; 97e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn if (*p != 0) { 98e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn *p = 0; 99e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn p++; 100e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } 101e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn mem[i] = atoll(num); 102e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn numFound++; 103e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn break; 104e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } 105e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn i++; 106e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } 10783b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn while (*p && *p != '\n') { 10883b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn p++; 10983b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn } 11083b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn if (*p) p++; 111e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } 112e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 11383b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn printf("RAM: %ldK total, %ldK free, %ldK buffers, %ldK cached, %ldK shmem, %ldK slab\n", 11483b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn mem[0], mem[1], mem[2], mem[3], mem[4], mem[5]); 115e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn} 116e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 117e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char *argv[]) { 118e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_kernel_t *ker; 119e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_process_t *proc; 120e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pid_t *pids; 12116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root struct proc_info **procs; 122e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project size_t num_procs; 123e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn unsigned long total_pss; 124e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn unsigned long total_uss; 12516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root char cmdline[256]; // this must be within the range of int 126e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int error; 127e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 128e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project #define WS_OFF 0 129e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project #define WS_ONLY 1 130e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project #define WS_RESET 2 131e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int ws; 132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 13316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root int arg; 13416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root size_t i, j; 135e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 136e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project compfn = &sort_by_pss; 137e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project order = -1; 138e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ws = WS_OFF; 139e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 14016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root for (arg = 1; arg < argc; arg++) { 14116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-v")) { compfn = &sort_by_vss; continue; } 14216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-r")) { compfn = &sort_by_rss; continue; } 14316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-p")) { compfn = &sort_by_pss; continue; } 14416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-u")) { compfn = &sort_by_uss; continue; } 14516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-w")) { ws = WS_ONLY; continue; } 14616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-W")) { ws = WS_RESET; continue; } 14716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-R")) { order *= -1; continue; } 14816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (!strcmp(argv[arg], "-h")) { usage(argv[0]); exit(0); } 14916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root fprintf(stderr, "Invalid argument \"%s\".\n", argv[arg]); 150e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project usage(argv[0]); 151e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 152e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 153e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 154e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = pm_kernel_create(&ker); 155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (error) { 156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Error creating kernel interface -- " 157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project "does this kernel have pagemap?\n"); 158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 159e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 160e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 161e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = pm_kernel_pids(ker, &pids, &num_procs); 162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (error) { 163e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Error listing processes.\n"); 164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 166e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 16716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root procs = calloc(num_procs, sizeof(struct proc_info*)); 16816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (procs == NULL) { 16916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root fprintf(stderr, "calloc: %s", strerror(errno)); 17016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root exit(EXIT_FAILURE); 17116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 17216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 173e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < num_procs; i++) { 174e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i] = malloc(sizeof(struct proc_info)); 17516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (procs[i] == NULL) { 176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "malloc: %s\n", strerror(errno)); 177e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 179e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->pid = pids[i]; 180eff788820689e7c2bfd456934e8132a381b31235Colin Cross pm_memusage_zero(&procs[i]->usage); 181e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = pm_process_create(ker, pids[i], &proc); 182eff788820689e7c2bfd456934e8132a381b31235Colin Cross if (error) { 183e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "warning: could not create process interface for %d\n", pids[i]); 184eff788820689e7c2bfd456934e8132a381b31235Colin Cross continue; 185eff788820689e7c2bfd456934e8132a381b31235Colin Cross } 186eff788820689e7c2bfd456934e8132a381b31235Colin Cross 187eff788820689e7c2bfd456934e8132a381b31235Colin Cross switch (ws) { 188eff788820689e7c2bfd456934e8132a381b31235Colin Cross case WS_OFF: 189eff788820689e7c2bfd456934e8132a381b31235Colin Cross error = pm_process_usage(proc, &procs[i]->usage); 190eff788820689e7c2bfd456934e8132a381b31235Colin Cross break; 191eff788820689e7c2bfd456934e8132a381b31235Colin Cross case WS_ONLY: 192eff788820689e7c2bfd456934e8132a381b31235Colin Cross error = pm_process_workingset(proc, &procs[i]->usage, 0); 193eff788820689e7c2bfd456934e8132a381b31235Colin Cross break; 194eff788820689e7c2bfd456934e8132a381b31235Colin Cross case WS_RESET: 195eff788820689e7c2bfd456934e8132a381b31235Colin Cross error = pm_process_workingset(proc, NULL, 1); 196eff788820689e7c2bfd456934e8132a381b31235Colin Cross break; 197e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 198eff788820689e7c2bfd456934e8132a381b31235Colin Cross 199eff788820689e7c2bfd456934e8132a381b31235Colin Cross if (error) { 200eff788820689e7c2bfd456934e8132a381b31235Colin Cross fprintf(stderr, "warning: could not read usage for %d\n", pids[i]); 201eff788820689e7c2bfd456934e8132a381b31235Colin Cross } 202eff788820689e7c2bfd456934e8132a381b31235Colin Cross 203eff788820689e7c2bfd456934e8132a381b31235Colin Cross pm_process_destroy(proc); 204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 205e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(pids); 207e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 208e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ws == WS_RESET) exit(0); 209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project j = 0; 211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < num_procs; i++) { 21216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (procs[i]->usage.vss) { 213e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[j++] = procs[i]; 21416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } else { 21516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root free(procs[i]); 21616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 217e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 218e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project num_procs = j; 219e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 220e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project qsort(procs, num_procs, sizeof(procs[0]), compfn); 221e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 222e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ws) 223e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5s %7s %7s %7s %s\n", "PID", "WRss", "WPss", "WUss", "cmdline"); 224e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project else 225e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5s %7s %7s %7s %7s %s\n", "PID", "Vss", "Rss", "Pss", "Uss", "cmdline"); 22616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 227e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn total_pss = 0; 228e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn total_uss = 0; 229e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 230e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < num_procs; i++) { 23116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (getprocname(procs[i]->pid, cmdline, (int)sizeof(cmdline)) < 0) { 23216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root /* 23316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * Something is probably seriously wrong if writing to the stack 23416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * failed. 23516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root */ 23616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root free(procs[i]); 23716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root continue; 23816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 23916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 240e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn total_pss += procs[i]->usage.pss; 241e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn total_uss += procs[i]->usage.uss; 242e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 243e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ws) 244e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5d %6dK %6dK %6dK %s\n", 245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->pid, 246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.rss / 1024, 247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.pss / 1024, 248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.uss / 1024, 249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project cmdline 250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ); 251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project else 252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%5d %6dK %6dK %6dK %6dK %s\n", 253e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->pid, 254e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.vss / 1024, 255e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.rss / 1024, 256e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.pss / 1024, 257e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project procs[i]->usage.uss / 1024, 258e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project cmdline 259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ); 26016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 26116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root free(procs[i]); 262e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 263e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 26416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root free(procs); 265e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 266e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn if (ws) { 267e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn printf("%5s %7s %7s %7s %s\n", 268e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "", "", "------", "------", "------"); 269e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn printf("%5s %7s %6ldK %6ldK %s\n", 270e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "", "", total_pss / 1024, total_uss / 1024, "TOTAL"); 271e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } else { 272e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn printf("%5s %7s %7s %7s %7s %s\n", 273e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "", "", "", "------", "------", "------"); 274e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn printf("%5s %7s %7s %6ldK %6ldK %s\n", 275e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn "", "", "", total_pss / 1024, total_uss / 1024, "TOTAL"); 276e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn } 277e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 278e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn printf("\n"); 279e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn print_mem_info(); 280e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn 281e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 282e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 283e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 284e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(char *myname) { 285e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Usage: %s [ -W ] [ -v | -r | -p | -u | -h ]\n" 286e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -v Sort by VSS.\n" 287e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -r Sort by RSS.\n" 288e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -p Sort by PSS.\n" 289e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -u Sort by USS.\n" 290e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " (Default sort order is PSS.)\n" 291e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -R Reverse sort order (default is descending).\n" 292e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -w Display statistics for working set only.\n" 293e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -W Reset working set of all processes.\n" 294e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -h Display this help screen.\n", 295e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project myname); 296e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 297e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 29816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root/* 29916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * Get the process name for a given PID. Inserts the process name into buffer 30016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * buf of length len. The size of the buffer must be greater than zero to get 30116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * any useful output. 30216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * 30316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * Note that fgets(3) only declares length as an int, so our buffer size is 30416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * also declared as an int. 30516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * 30616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * Returns 0 on success, a positive value on partial success, and -1 on 30716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * failure. Other interesting values: 30816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * 1 on failure to create string to examine proc cmdline entry 30916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * 2 on failure to open proc cmdline entry 31016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * 3 on failure to read proc cmdline entry 31116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root */ 31216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootstatic int getprocname(pid_t pid, char *buf, int len) { 31316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root char *filename; 314e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project FILE *f; 31516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root int rc = 0; 31616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root static const char* unknown_cmdline = "<unknown>"; 31716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 31816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (len <= 0) { 31916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root return -1; 32016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 32116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 32216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (asprintf(&filename, "/proc/%zd/cmdline", pid) < 0) { 32316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root rc = 1; 32416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root goto exit; 32516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 326e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 327e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project f = fopen(filename, "r"); 32816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (f == NULL) { 32916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root rc = 2; 33016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root goto releasefilename; 33116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 33216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 33316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (fgets(buf, len, f) == NULL) { 33416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root rc = 3; 33516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root goto closefile; 33616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 33716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 33816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootclosefile: 33916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root (void) fclose(f); 34016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootreleasefilename: 34116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root free(filename); 34216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootexit: 34316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (rc != 0) { 34416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root /* 34516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * The process went away before we could read its process name. Try 34616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * to give the user "<unknown>" here, but otherwise they get to look 34716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * at a blank. 34816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root */ 34916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) { 35016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root rc = 4; 35116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 35216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root } 35316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root 35416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root return rc; 355e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 356e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(long long a, long long b) { 358e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (a < b) return -1; 359e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (a > b) return 1; 360e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 362e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 363e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define create_sort(field, compfn) \ 364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project static int sort_by_ ## field (const void *a, const void *b) { \ 365e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return order * compfn( \ 366e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project (*((struct proc_info**)a))->usage.field, \ 367e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project (*((struct proc_info**)b))->usage.field \ 368e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ); \ 369e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 370e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 371e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(vss, numcmp) 372e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(rss, numcmp) 373e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(pss, numcmp) 374e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(uss, numcmp) 375