busybox 中的top 不支持查看线程, 因此查询相关资料自己写了一个, 对比测试跟linux 标准的top数据一致。另外,需要注意的是,
pthread_create(&task_id,...) 的task_id和tid不同,
需要做一个对应:
#include <sys/syscall.h>
printf("%u --> tid %u\n", pthread_self(), syscall(SYS_gettid));
不啰嗦了,附源码:
/* top_thread.c -- mimic "top -H -p pid" * author: ludi 2013.11 doc: $ cat /proc/stat cpu 3723999 28230 813821 136182538 6215783 187445 373893 0 user, nice, sys, idle, irq, softirq, stealstolen, guest $ cat /proc/31628/stat 31628 (pdflush) S 19 1 1 0 -1 8400960 0 0 0 0 0 161 0 0 15 0 1 0 36070699 0 0 4294967295 0 0 0 0 0 0 2147483647 65536 0 0 0 0 17 2 0 0 2648 $ cat /proc/31628/task/31628/stat 31628 (pdflush) S 19 1 1 0 -1 8400960 0 0 0 0 0 161 0 0 15 0 1 0 36070699 0 0 4294967295 0 0 0 0 0 0 2147483647 65536 0 0 0 0 17 2 0 0 2648 1 2 3 4 5 6 7 8 9 10--13 14------17 18-20 21-----------------------------29 30---------------33 pid comm state ppid pgid sid tty_nr tty_pgrp 1-8 flags 9 flt_{min, cmin, maj, cmaj}10-13 time_{u,s,cu,cs} 14-17 priority nice num_threads 18-20 start_time vsize mm rsslim start_code end_code start_stack esp eip 21-29 sig_{pending, blocked, ign, catch} 30-33 ULL totalCpuTime; //from /proc/stat ULL processCpuTime; //from /proc/<pid>/stat ULL threadCpuTime; //from /proc/<pid>/task/<tid>/stat totalCpuTime = user + nice + system + idle + iowait + irq + softirq + stealstolen + guest; processCpuTime = utime + stime + cutime + cstime; threadCpuTime = utime + stime; pthread_create(&task_id,...) 的task_id和tid不同, 需要做一个对应: #include <sys/syscall.h> printf("%u --> tid %u\n", pthread_self(), syscall(SYS_gettid)); */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include<sys/stat.h> #include <unistd.h> /*fstat*/ #include <dirent.h> /*opendir*/ #define THREAD_MAX 512 typedef unsigned long long ULL; typedef struct{ ULL total, idle; ULL process; int tcnt; unsigned tid[THREAD_MAX]; ULL ttime[THREAD_MAX]; }cpu_time_t; typedef struct{ unsigned tid; float usage; }sorted_time_t; int sorted_time_cmp(const void *a, const void *b) { return ((sorted_time_t*)b)->usage - ((sorted_time_t*)a)->usage; } ULL get_ttime(cpu_time_t *ct, unsigned tid) { int i; for(i = 0; i < ct->tcnt; ++i){ if(ct->tid[i] == tid)return ct->ttime[i]; } return 0; } int get_tids(unsigned pid, unsigned tids[], int *cnt) { DIR *dp; struct dirent *entry; struct stat statbuf; char dir[64]; int num; if(!tids || !cnt){printf("bad arg"); return -1;} sprintf(dir, "/proc/%u/task", pid); if(NULL == (dp = opendir(dir))){ printf("can not open directory :%s\n",dir); exit( -1); } num = 0; while(NULL != (entry = readdir(dp))){ stat(entry->d_name,&statbuf); if(S_ISDIR(statbuf.st_mode) &&(!strcmp(".",entry->d_name)||!strcmp("..",entry->d_name)) ){continue;} tids[num] = atoi(entry->d_name); num++; if(num >= *cnt){break;} } closedir(dp); *cnt = num; return 0; } int get_processor_cnt(void) { FILE *fp; char name[64]; int cnt; sprintf(name, "%s", "/proc/cpuinfo"); fp = fopen(name, "r"); if(!fp){printf("can't open %s\n", name); exit(-1);} cnt = 0; while(fgets(name, sizeof(name), fp)){ if(!strncmp(name, "processor", strlen("processor")) ||!strncmp(name, "Processor", strlen("Processor")) ){++cnt;} } fclose(fp); if(!cnt){ printf("set processor cnt to default 1"); cnt = 1; } return cnt; } ULL cpu_time_snap_cpu(ULL *idle_) { ULL user, nice, sys, idle, irq, softirq, stealstolen, guest; ULL totalCpuTime; FILE *fp; char name[64]; sprintf(name, "%s", "/proc/stat"); fp = fopen(name, "r"); if(!fp)exit(-1); fscanf(fp, "%*s%llu%llu%llu%llu%llu%llu%llu%llu", &user, &nice, &sys, &idle, &irq, &softirq, &stealstolen, &guest); fclose(fp); totalCpuTime = user + nice + sys + idle + irq + softirq + stealstolen + guest; *idle_ = idle; return totalCpuTime; } ULL cpu_time_snap_process(ULL pid) { ULL utime, stime, cutime, cstime; ULL processCpuTime; FILE *fp; char name[64]; sprintf(name, "/proc/%llu/stat", pid); fp = fopen(name, "r"); if(!fp)exit(-1); fscanf(fp, "%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s"); fscanf(fp, "%llu%llu%llu%llu", &utime, &stime, &cutime, &cstime); fclose(fp); processCpuTime = utime + stime + cutime + cstime; return processCpuTime; } ULL cpu_time_snap_thread(ULL pid, ULL tid) { ULL utime, stime, cutime, cstime; ULL threadCpuTime; FILE *fp; char name[64]; sprintf(name, "/proc/%llu/task/%llu/stat", pid, tid); fp = fopen(name, "r"); if(!fp)return 0;//exit(-1); fscanf(fp, "%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s"); fscanf(fp, "%llu%llu%llu%llu", &utime, &stime, &cutime, &cstime); fclose(fp); threadCpuTime = utime + stime; return threadCpuTime; } ULL cpu_time_snap(unsigned pid) { static int is_first = 1, processor_cnt = 0; static cpu_time_t last_ct = {0}; static sorted_time_t st[THREAD_MAX]; ULL delta_totalCpuTime, delta_idle, delta_processCpuTime, delta_threadCpuTime; cpu_time_t ct = {0}; float pcpu[4]; int i; if(is_first){processor_cnt = get_processor_cnt();} ct.tcnt = THREAD_MAX; get_tids(pid, ct.tid, &ct.tcnt); ct.total = cpu_time_snap_cpu(&ct.idle); ct.process = cpu_time_snap_process(pid); for(i = 0; i < ct.tcnt; ++i){ ct.ttime[i] = cpu_time_snap_thread(pid, ct.tid[i]); } if(is_first)goto _end; delta_totalCpuTime = ct.total - last_ct.total; delta_idle = ct.idle - last_ct.idle; delta_processCpuTime = ct.process - last_ct.process; if(!delta_totalCpuTime)return 0; //cpu usage pcpu[0] = 100*(delta_totalCpuTime - delta_idle)/(float)delta_totalCpuTime *processor_cnt; //process usage pcpu[1] = 100*delta_processCpuTime/(float)delta_totalCpuTime *processor_cnt; printf("\033[H\033[J"); printf("cpu %.2f process %.2f\n", pcpu[0], pcpu[1]); //thread usage for(i = 0; i < ct.tcnt; ++i){ delta_threadCpuTime = ct.ttime[i] - get_ttime(&last_ct, ct.tid[i]); pcpu[2] = 100*delta_threadCpuTime/(float)delta_totalCpuTime *processor_cnt; st[i].tid = ct.tid[i]; st[i].usage = pcpu[2]; } qsort(st, ct.tcnt, sizeof(st[0]), sorted_time_cmp); for(i = 0; i < ct.tcnt; ++i){ printf("%u:%.2f\t", st[i].tid, st[i].usage); } printf("tcnt %d", ct.tcnt); fflush(stdout); _end: last_ct = ct; is_first = 0; return delta_totalCpuTime; } int main(int argc, char **argv) { int i; //Hertz = sysconf(_SC_CLK_TCK); //printf("HZ %u\n", Hertz); if(argc < 2){return printf("usage: topH pid\n");} cpu_time_snap(atoi(argv[1])); for(i = 0; ; ++i){ cpu_time_snap(atoi(argv[1])); usleep(1000000*1); } return 0; }