kgmon.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 493 行

C
493
字号
#ifndef lintstatic char sccsid[] = "@(#)kgmon.c	4.1	(ULTRIX)	7/2/90";#endif lint/* * Based on: * static char sccsid[] = "@(#)kgmon.c	4.9 (Berkeley) 83/08/11"; *//************************************************************************ *									* *			Copyright (c) 1984 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Modification history * *20-Jun-88	jaw   *	kgmon now dumps out kernel profiling data for multiple  *	processors.  Format dumped is not compatible with gprof.  Must *	run the kgdump.out though the kgconv program.  Manual page  *	must be update for smp release. *  */#include <sys/param.h>#include <machine/pte.h>#include <sys/vm.h>#include <stdio.h>#include <nlist.h>#include <ctype.h>#include <sys/gprof.h>/* * froms is actually a bunch of unsigned shorts indexing tos */u_short			*froms;struct	tostruct	*tos;char			*s_lowpc;u_long			s_textsize;int			ssiz;off_t			sbuf;struct nlist nl[] = {#define	N_SYSMAP	0	{ "_Sysmap" },#define	N_SYSSIZE	1	{ "_Syssize" },#define N_FROMS		2	{ "_froms" },#define	N_PROFILING	3	{ "_profiling" },#define	N_S_LOWPC	4	{ "_s_lowpc" },#define	N_S_TEXTSIZE	5	{ "_s_textsize" },#define	N_SBUF		6	{ "_sbuf" },#define N_SSIZ		7	{ "_ssiz" },#define	N_TOS		8	{ "_tos" },#define	N_TOSTRUCTSIZE	9	{ "_tostruct_size" },	0,};struct	pte *Sysmap;char	*progname;char	*dumpfile =	"kgdump.out";char	*sysfile =	"/vmunix";char	*kmemf =	"/dev/kmem";int	kmem;int	bflag, hflag, kflag, rflag, pflag;char	*malloc();void	exit(), perror(), nlist();long	klseek();long	lseek();main(argc, argv)	int argc;	char *argv[];{	int mode, disp, openmode = 0;	progname = argv[0];	argc--, argv++;	while (argc > 0 && argv[0][0] == '-') {		switch (argv[0][1]) {		case 'b':			bflag++;			openmode = 2;			break;		case 'h':			hflag++;			openmode = 2;			break;		case 'r':			rflag++;			openmode = 2;			break;		case 'p':			pflag++;			openmode = 2;			break;		default:			(void) fprintf(stderr,				"Usage: %s [ -b -h -r -p sysfile memory ]\n",				progname);			exit(1);		}		argc--, argv++;	}	if (argc > 0) {		sysfile = *argv;#ifdef DEBUG		(void) fprintf(stderr,"Using sysfile = %s\n",sysfile);#endif DEBUG		argv++, argc--;	}	nlist(sysfile, nl);	if (nl[0].n_type == 0) {		(void) fprintf(stderr, "%s: %s has no namelist\n",			progname, sysfile);		exit(2);	}	if (argc > 0) {		kmemf = *argv;#ifdef DEBUG		(void) fprintf(stderr,"Using kmemfile = %s\n",kmemf);#endif DEBUG		kflag++;	}	kmem = open(kmemf, openmode);	if (kmem < 0) {		openmode = 0;		kmem = open(kmemf, openmode);		if (kmem < 0) {			(void) fprintf(stderr, "%s: cannot open ", progname);			perror(kmemf);			exit(3);		}		(void) fprintf(stderr, "%s opened read-only\n", kmemf);		if (rflag)			(void) fprintf(stderr, "-r supressed\n");		if (bflag)			(void) fprintf(stderr, "-b supressed\n");		if (hflag)			(void) fprintf(stderr, "-h supressed\n");		rflag = 0;		bflag = 0;		hflag = 0;	}	if (kflag) {		off_t off;		off = nl[N_SYSMAP].n_value & 0x7fffffff;		if (lseek(kmem, (long)off, 0) == -1) {			(void) fprintf(stderr,"%s: ",progname);			perror("lseek");		}		nl[N_SYSSIZE].n_value *= 4;		Sysmap = (struct pte *)malloc((unsigned)nl[N_SYSSIZE].n_value);		if (Sysmap == 0) {			(void) fprintf(stderr,"%s: ",progname);			perror("Sysmap");			exit(4);		}		if (read(kmem, (char *)Sysmap, (int) nl[N_SYSSIZE].n_value) !=			(int) nl[N_SYSSIZE].n_value) {			(void) fprintf(stderr,"%s: ",progname);			perror("read");			exit(5);		}	}	mode = kfetch(N_PROFILING);	if (hflag)		disp = PROFILING_OFF;	else if (bflag)		disp = PROFILING_ON;	else		disp = mode;	if (pflag) {		if (openmode == 0 && mode == PROFILING_ON)			(void) fprintf(stderr, "%s: data may be inconsistent\n",				progname);		dumpstate();	}	if (rflag)		resetstate();	turnonoff(disp);	(void) printf("Kernel profiling is %s.\n",disp?"off":"running");}/* *	SMP changes: *	The layout of the dump file is: *	4 bytes for ssiz *	ssiz bytes of sbuf (the time counters) *	4 bytes for s_textsize *	4 bytes for s_lowpc *	4 bytes for fromssize *	fromssize bytes of the from structure *	4 bytes for number of tostructs *	4 bytes for the tossize *	tossize bytes of the tostruct (variable size because of NCPU) */dumpstate(){	register int i,j;	int fd;	off_t kfroms, ktos;	int fromssize, tossize, num_tostructs, to_struct_size;	char buf[BUFSIZ];	turnonoff(PROFILING_OFF);	fd = creat(dumpfile, 0666);	if (fd < 0) {		(void) fprintf(stderr,"%s: ", progname);		perror(dumpfile);		return;		/* print the debugging state on return */	}	ssiz = kfetch(N_SSIZ);	/* dump ssiz */	if (write(fd,(char *)&ssiz,sizeof(ssiz)) != sizeof(ssiz)) {		(void) fprintf(stderr,"%s: ",progname);		perror("write");		return;	}	sbuf = kfetch(N_SBUF);	if (klseek(kmem, (off_t)sbuf, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		return;	}	for (i = ssiz; i > 0; i -= BUFSIZ) {		j = (i < BUFSIZ ? i : BUFSIZ);		if (read(kmem, buf, j) != j) {			(void) fprintf(stderr,"%s: ",progname);			perror("read");			return;		}		/* dump the time counters */		if (write(fd, buf, j) != j) {			(void) fprintf(stderr,"%s: ",progname);			perror("write");			return;		}	}	s_textsize = kfetch(N_S_TEXTSIZE);	/* dump the textsize */	if (write(fd,(char *)&s_textsize,sizeof(s_textsize)) !=	sizeof(s_textsize)) {		(void) fprintf(stderr,"%s: ",progname);		perror("write");		return;	}	s_lowpc = (char *)kfetch(N_S_LOWPC);	/* dump the lowest pc */	if (write(fd,(char *)&s_lowpc,sizeof(s_lowpc)) != sizeof(s_lowpc)) {		(void) fprintf(stderr,"%s: ",progname);		perror("write");		return;	}	fromssize = s_textsize / HASHFRACTION;	/* dump the fromsize */	if (write(fd,(char *)&fromssize,sizeof(fromssize)) !=	sizeof(fromssize)){		(void) fprintf(stderr,"%s: ",progname);		perror("write");		return;	}	froms = (u_short *)malloc((unsigned)fromssize);	kfroms = kfetch(N_FROMS);	if (klseek(kmem, kfroms, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		return;	}	i = read(kmem, ((char *)(froms)), fromssize);	if (i != fromssize) {		(void) fprintf(stderr,"%s: ", progname);		(void) fprintf(stderr, "read froms: request %d, got %d",			fromssize, i);		perror("");		return;	}	/* dump the froms structures */	if (write(fd,(char *)froms,fromssize) != fromssize) {		(void) fprintf(stderr,"%s: ", progname);		perror("write");		return;	}	num_tostructs = (s_textsize * ARCDENSITY / 100);	/* dump the number of to structures */	if (write(fd,(char *)&num_tostructs,sizeof(num_tostructs)) !=		sizeof(num_tostructs)) {		(void) fprintf(stderr,"%s: ", progname);		perror("write");		return;	}	to_struct_size = kfetch(N_TOSTRUCTSIZE);	/* dump the size of the tostruct */	if (write(fd,(char *)&to_struct_size,sizeof(to_struct_size)) !=		sizeof(to_struct_size)) {		(void) fprintf(stderr,"%s: ", progname);		perror("write");		return;	}	/* the last two numbers combine to allow kgconv/kgdump */	/* to figure out how many cpus there are */	tossize = num_tostructs * to_struct_size;	tos = (struct tostruct *)malloc((unsigned)tossize);	ktos = kfetch(N_TOS);	if (klseek(kmem, ktos, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		return;	}	i = read(kmem, ((char *)(tos)), tossize);	if (i != tossize) {		(void) fprintf(stderr,"%s: ", progname);		(void) fprintf(stderr, "read tos: request %d, got %d",			tossize, i);		perror("");		return;	}	/* dump the to structures */	if (write(fd,(char *)tos,tossize) != tossize) {		(void) fprintf(stderr,"%s: ", progname);		perror("write");		return;	}	if (close(fd) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("close");		return;	}}resetstate(){	int i;	off_t kfroms, ktos;	int fromssize, tossize;	char buf[BUFSIZ];	turnonoff(PROFILING_OFF);	bzero(buf, BUFSIZ);	ssiz = kfetch(N_SSIZ);	sbuf = kfetch(N_SBUF);	ssiz -= sizeof(struct phdr);	sbuf += sizeof(struct phdr);	if (klseek(kmem, (off_t)sbuf, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		exit(6);	}	for (i = ssiz; i > 0; i -= BUFSIZ)		if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {			(void) fprintf(stderr,"%s: ", progname);			perror("sbuf write");			exit(7);		}	s_textsize = kfetch(N_S_TEXTSIZE);	fromssize = s_textsize / HASHFRACTION;	kfroms = kfetch(N_FROMS);	if (klseek(kmem, kfroms, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		exit(8);	}	for (i = fromssize; i > 0; i -= BUFSIZ)		if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {			(void) fprintf(stderr,"%s: ", progname);			perror("kfroms write");			exit(9);		}	tossize = (s_textsize * ARCDENSITY / 100) * (kfetch(N_TOSTRUCTSIZE));	ktos = kfetch(N_TOS);	if (klseek(kmem, ktos, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		exit(10);	}	for (i = tossize; i > 0; i -= BUFSIZ)		if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {			(void) fprintf(stderr,"%s: ", progname);			perror("ktos write");			exit(11);		}}turnonoff(onoff)	int onoff;{	off_t off;	if ((off = nl[N_PROFILING].n_value) == 0) {		(void) fprintf(stderr,"%s: profiling not defined in kernel\n",			progname);		exit(12);	}#ifdef DEBUG	(void)fprintf(stderr,"turnonoff: seeking on kmem to offset 0x%x\n",off);#endif DEBUG	if (klseek(kmem, off, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		exit(13);	}#ifdef DEBUG	(void) fprintf(stderr,"turnonoff: Writing kmem at offset 0x%x\n",off);#endif DEBUG	if (write(kmem, (char *)&onoff, sizeof (onoff)) != sizeof(onoff)) {		(void) fprintf(stderr,"%s: ",progname);		perror("write");		exit(14);	}}kfetch(index)	int index;{	off_t off;	int value;	if ((off = nl[index].n_value) == 0) {		(void) fprintf(stderr,"%s: %s not defined in kernel\n",			progname, nl[index].n_name);		exit(15);	}#ifdef DEBUG	(void) fprintf(stderr,"kfetch: for %s ",nl[index].n_name);#endif DEBUG	if (klseek(kmem, off, 0) == -1) {		(void) fprintf(stderr,"%s: ", progname);		perror("lseek");		exit(16);	}	if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) {		(void) fprintf(stderr,"%s: ", progname);		perror("read");		exit(17);	}#ifdef DEBUG	if (value < 0) {		(void) fprintf(stderr,"got 0x%x\n",value);	}	else {		(void) fprintf(stderr,"got %d\n",value);	}#endif DEBUG	return (value);}longklseek(fd, base, off)	int fd, base, off;{	if (kflag) {		/* get kernel pte */#if vax		base &= 0x7fffffff;#endif		base = ((int)ptob(Sysmap[btop(base)].pg_pfnum))+(base&(NBPG-1));	}	return (lseek(fd, (long) base, off));}

⌨️ 快捷键说明

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