1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <ctype.h> 4 #include <fcntl.h> 5 6 #include <string.h> 7 8 #include <sys/stat.h> 9 #include <sys/types.h> 10 #include <dirent.h> 11 12 #include <pwd.h> 13 14 #include <cutils/sched_policy.h> 15 16 17 static char *nexttoksep(char **strp, char *sep) 18 { 19 char *p = strsep(strp,sep); 20 return (p == 0) ? "" : p; 21 } 22 static char *nexttok(char **strp) 23 { 24 return nexttoksep(strp, " "); 25 } 26 27 #define SHOW_PRIO 1 28 #define SHOW_TIME 2 29 #define SHOW_POLICY 4 30 31 static int display_flags = 0; 32 33 static int ps_line(int pid, int tid, char *namefilter) 34 { 35 char statline[1024]; 36 char cmdline[1024]; 37 char user[32]; 38 struct stat stats; 39 int fd, r; 40 char *ptr, *name, *state; 41 int ppid, tty; 42 unsigned wchan, rss, vss, eip; 43 unsigned utime, stime; 44 int prio, nice, rtprio, sched; 45 struct passwd *pw; 46 47 sprintf(statline, "/proc/%d", pid); 48 stat(statline, &stats); 49 50 if(tid) { 51 sprintf(statline, "/proc/%d/task/%d/stat", pid, tid); 52 cmdline[0] = 0; 53 } else { 54 sprintf(statline, "/proc/%d/stat", pid); 55 sprintf(cmdline, "/proc/%d/cmdline", pid); 56 fd = open(cmdline, O_RDONLY); 57 if(fd == 0) { 58 r = 0; 59 } else { 60 r = read(fd, cmdline, 1023); 61 close(fd); 62 if(r < 0) r = 0; 63 } 64 cmdline[r] = 0; 65 } 66 67 fd = open(statline, O_RDONLY); 68 if(fd == 0) return -1; 69 r = read(fd, statline, 1023); 70 close(fd); 71 if(r < 0) return -1; 72 statline[r] = 0; 73 74 ptr = statline; 75 nexttok(&ptr); // skip pid 76 ptr++; // skip "(" 77 78 name = ptr; 79 ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')', 80 *ptr++ = '\0'; // and null-terminate name. 81 82 ptr++; // skip " " 83 state = nexttok(&ptr); 84 ppid = atoi(nexttok(&ptr)); 85 nexttok(&ptr); // pgrp 86 nexttok(&ptr); // sid 87 tty = atoi(nexttok(&ptr)); 88 89 nexttok(&ptr); // tpgid 90 nexttok(&ptr); // flags 91 nexttok(&ptr); // minflt 92 nexttok(&ptr); // cminflt 93 nexttok(&ptr); // majflt 94 nexttok(&ptr); // cmajflt 95 #if 1 96 utime = atoi(nexttok(&ptr)); 97 stime = atoi(nexttok(&ptr)); 98 #else 99 nexttok(&ptr); // utime 100 nexttok(&ptr); // stime 101 #endif 102 nexttok(&ptr); // cutime 103 nexttok(&ptr); // cstime 104 prio = atoi(nexttok(&ptr)); 105 nice = atoi(nexttok(&ptr)); 106 nexttok(&ptr); // threads 107 nexttok(&ptr); // itrealvalue 108 nexttok(&ptr); // starttime 109 vss = strtoul(nexttok(&ptr), 0, 10); // vsize 110 rss = strtoul(nexttok(&ptr), 0, 10); // rss 111 nexttok(&ptr); // rlim 112 nexttok(&ptr); // startcode 113 nexttok(&ptr); // endcode 114 nexttok(&ptr); // startstack 115 nexttok(&ptr); // kstkesp 116 eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip 117 nexttok(&ptr); // signal 118 nexttok(&ptr); // blocked 119 nexttok(&ptr); // sigignore 120 nexttok(&ptr); // sigcatch 121 wchan = strtoul(nexttok(&ptr), 0, 10); // wchan 122 nexttok(&ptr); // nswap 123 nexttok(&ptr); // cnswap 124 nexttok(&ptr); // exit signal 125 nexttok(&ptr); // processor 126 rtprio = atoi(nexttok(&ptr)); // rt_priority 127 sched = atoi(nexttok(&ptr)); // scheduling policy 128 129 tty = atoi(nexttok(&ptr)); 130 131 if(tid != 0) { 132 ppid = pid; 133 pid = tid; 134 } 135 136 pw = getpwuid(stats.st_uid); 137 if(pw == 0) { 138 sprintf(user,"%d",(int)stats.st_uid); 139 } else { 140 strcpy(user,pw->pw_name); 141 } 142 143 if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) { 144 printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4); 145 if(display_flags&SHOW_PRIO) 146 printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched); 147 if (display_flags & SHOW_POLICY) { 148 SchedPolicy p; 149 if (get_sched_policy(pid, &p) < 0) 150 printf(" un "); 151 else { 152 if (p == SP_BACKGROUND) 153 printf(" bg "); 154 else if (p == SP_FOREGROUND) 155 printf(" fg "); 156 else 157 printf(" er "); 158 } 159 } 160 printf(" %08x %08x %s %s", wchan, eip, state, cmdline[0] ? cmdline : name); 161 if(display_flags&SHOW_TIME) 162 printf(" (u:%d, s:%d)", utime, stime); 163 164 printf("\n"); 165 } 166 return 0; 167 } 168 169 170 void ps_threads(int pid, char *namefilter) 171 { 172 char tmp[128]; 173 DIR *d; 174 struct dirent *de; 175 176 sprintf(tmp,"/proc/%d/task",pid); 177 d = opendir(tmp); 178 if(d == 0) return; 179 180 while((de = readdir(d)) != 0){ 181 if(isdigit(de->d_name[0])){ 182 int tid = atoi(de->d_name); 183 if(tid == pid) continue; 184 ps_line(pid, tid, namefilter); 185 } 186 } 187 closedir(d); 188 } 189 190 int ps_main(int argc, char **argv) 191 { 192 DIR *d; 193 struct dirent *de; 194 char *namefilter = 0; 195 int pidfilter = 0; 196 int threads = 0; 197 198 d = opendir("/proc"); 199 if(d == 0) return -1; 200 201 while(argc > 1){ 202 if(!strcmp(argv[1],"-t")) { 203 threads = 1; 204 } else if(!strcmp(argv[1],"-x")) { 205 display_flags |= SHOW_TIME; 206 } else if(!strcmp(argv[1],"-P")) { 207 display_flags |= SHOW_POLICY; 208 } else if(!strcmp(argv[1],"-p")) { 209 display_flags |= SHOW_PRIO; 210 } else if(isdigit(argv[1][0])){ 211 pidfilter = atoi(argv[1]); 212 } else { 213 namefilter = argv[1]; 214 } 215 argc--; 216 argv++; 217 } 218 219 printf("USER PID PPID VSIZE RSS %s %s WCHAN PC NAME\n", 220 (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"", 221 (display_flags&SHOW_POLICY)?"PCY " : ""); 222 while((de = readdir(d)) != 0){ 223 if(isdigit(de->d_name[0])){ 224 int pid = atoi(de->d_name); 225 if(!pidfilter || (pidfilter == pid)) { 226 ps_line(pid, 0, namefilter); 227 if(threads) ps_threads(pid, namefilter); 228 } 229 } 230 } 231 closedir(d); 232 return 0; 233 } 234 235