⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 profile.c

📁 实现了poll/epoll/devpoll等C++封装
💻 C
字号:
/* * Original by Ramon Garcia Fernandez <ramon@juguete.quim.ucm.es> * Hacked by linus * then mingo broke it all * and dank made it take the profile data filename as an argument */#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <fcntl.h>#include <sys/stat.h>#define prof_func "sys_open"#define BUFSIZE 1024struct entry {	struct entry * next;	long long time;	/*			 * With APIC irqs we can get more than			 * 4G profiling hits.			 */	unsigned long address;	char type; 	/*			 * We profile only functions currently,			 * so we can do some sanity checking by analyzing			 * the symbol type field in System.map			 */	char name[1];};struct entry * list = NULL;static void do_symbol(long long time, unsigned long address, char * name, char type){	struct entry * entry = malloc(sizeof(struct entry) + strlen(name));	struct entry ** tmp;	entry->time = time;	entry->address = address;	strcpy(entry->name, name + (*name == '_'));	entry->type = type;	tmp = &list;	while (*tmp) {		if ((*tmp)->time > entry->time)			break;		tmp = &(*tmp)->next;	}	entry->next = *tmp;	*tmp = entry;}static void show_symbols(long long total){	int had_type_conflict=0;	struct entry * entry = list;	long long sanity_total=0;	printf("\n//\n// Function granularity sorted histogram:\n");	printf("//---------------------------------------\n");	while (entry) {		printf("%12Ld %5Ld.%02Ld%% %08lx %s\n" ,			entry->time,			(entry->time*10000/total) / 100,			(entry->time*10000/total) % 100,			entry->address, entry->name);		if ((entry->type != 't') && (entry->type != 'T')) {			had_type_conflict=1;			printf("// TYPE CONFLICT (type:'%c', symbol:'%s').\n",					entry->type,entry->name);		}		sanity_total += entry->time;		entry = entry->next;	}	printf("//-----------------------------\n");	printf("%12Ld   100.00%% 00000000 TOTAL\n" ,total);	if (total != sanity_total) 		printf("WARNING: sum of times(%Ld) != total.\n", sanity_total);	if (had_type_conflict) {		fprintf(stderr, "\n// WARNING: type conflict detected.");		fprintf(stderr, " (wrong System.map?)\n");#if 0		// this warning appears to be spurious - wonder what's wrong?		exit(1);#endif	}}static inline void show_finegrained_function (int has_read, int * buffer, int step,					 char * func, int addr){	long long sum=0;	int i;	for ( i = 0 ; i < has_read/(int)sizeof(int) ; i++)		sum += buffer[i];	if (!sum)		printf("// (no profiling hits in %s()).\n", func);	else {		printf("// Fine grained profile of %s().\n", func);		printf("//\n");		printf("// TOTAL:   100.000000%%  %12Ld\n", sum);		printf("//-----------------------------------\n");		for ( i = 0 ; i < has_read/(int)sizeof(int) ; i++) {			/*			 * Could someone please enhance/fix printf's %f			 * conversion type? This workaround to get proper			 * padding and position is _soooo_ silly.			 */			printf("   %08x %3Ld.%06Ld%%  %12d\n",				i*step + addr,				 ((long long)buffer[i]*100)/sum,				(((long long)buffer[i]*100)%sum)*1000000/sum,				buffer[i]			);		}	}}/* If you do not speak Spanish: * valor_simbolo_actual: current_symbol_value * valor_simbolo_siguiente: next_symbol_value * simbolo_actual: current_symbol * next_symbol: next_symbol * leidos: read (past participle) * total: total*/int main(int argc, char ** argv){	int fp;	const char * func = prof_func;	FILE *kmap;	int current_symbol_value , next_symbol_value, code_offset;	char current_symbol[80] , next_symbol[80];	int has_read , j;	long long total=0;	off_t profile_size;	unsigned long end_address=0;	const char *fname = "/proc/profile";	int step;	/*			 * We can read the profiling step from			 * /proc/profile directly, so we are not			 * compilation dependent			 */	char type;	int found_function=0, 	    just_found_function=0;     /*					* This is needed for ultra-low					* resolution profiling.					*/	if (argc >= 2)		func = argv[1];	if (argc >= 3)		fname = argv[2];	fp = open(fname, O_RDONLY);	if (fp < 0) {		perror(fname);		exit(1);	}	kmap = fopen("/System.map","r");	if (!kmap) {		kmap = fopen("/usr/src/linux/System.map","r");		if (!kmap) {			perror("System.map");			exit(1);		}	}/* * The size of /proc/profile is a very good sanity check, it should end * with _etext. If not the System.map is bolixed. */	{		struct stat statbuf;		fstat (fp, &statbuf);		profile_size=statbuf.st_size;	}	fscanf(kmap, "%x %*s %s\n", &current_symbol_value, current_symbol);	fscanf(kmap, "%x %c %s\n", &next_symbol_value, &type, next_symbol);/* * We expect the _stext symbol here. This is both necessary and a good * sanity check. */	if (	strcmp(current_symbol,"_stext") &&	 	strcmp(current_symbol,"_text")		) {		fprintf(stderr,		   "expecting _text or _stext as first System.map symbol.\n%s",		   "(maybe stray undefined symbols in System.map?).\n");		exit(1);	}	code_offset=current_symbol_value;/* * Here we read the profiling step from /proc/profile. This is a good * sanity check as well. Nothing should go wrong after this. */	has_read = read (fp , &step , sizeof(step) );	if (has_read != (int)sizeof(int)) {		perror("huh, couldnt read step from /proc/profile.");		exit(1);	}	printf("// Step: %d, Profiling %s().\n\n",step, func);	/*	 * Main read-analyze loop.	 */	for (;;) {		unsigned long long tiempo = 0;		unsigned int buffer [(next_symbol_value -					 current_symbol_value)/step];		if (!strcmp(func, current_symbol)) {			found_function=1;			just_found_function=1;		}		if (!strcmp("_etext", current_symbol))			end_address=next_symbol_value;		if ((next_symbol_value/step) == (current_symbol_value/step)) {			strcpy(current_symbol, next_symbol);			fscanf(kmap, "%x %c %s\n", &next_symbol_value,							&type, next_symbol);			continue;		}		lseek (fp , sizeof(int)+				(current_symbol_value-code_offset)/step*					sizeof(int) ,			 SEEK_SET);		has_read = read (fp , buffer , sizeof(buffer) );		if (just_found_function) {			just_found_function=0;			show_finegrained_function(has_read, buffer, step,				current_symbol, current_symbol_value);		}		for ( j = 0 ; j < has_read/(int)sizeof(int) ; j++)			tiempo += buffer[j];		if (tiempo != 0) {			do_symbol(tiempo, current_symbol_value,						current_symbol, type);			total += tiempo;		}		if ((has_read < (next_symbol_value-current_symbol_value)/				step*(int)sizeof(int)) || 			next_symbol_value == current_symbol_value )			break;		strcpy ( current_symbol , next_symbol );		current_symbol_value = next_symbol_value;		fscanf(kmap , "%x %c %s\n" ,			 &next_symbol_value , &type, next_symbol );	}	show_symbols(total);	if ( abs((int)(profile_size-sizeof(int))/sizeof(int)*step			-(end_address-code_offset)) > (int)step) {		fprintf(stderr,"\n// WARNING: wrong _etext symbol.\n");		fprintf(stderr,"//          (wrong System.map?)\n");		exit(1);	}	if (!found_function) {		fprintf(stderr,"\n// WARNING: Symbol '%s' not in System.map.\n",				func);		exit(1);	}	return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -