查看线程的cpu使用率

        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;
}


你可能感兴趣的:(c,linux)