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

📄 m_macosx.c

📁 unix系统下top命令的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * m_macosx.c * * AUTHOR:	Andrew S. Townley *		based on m_bsd44.c and m_next32.c *		by Christos Zoulas and Tim Pugh * CREATED:	Tue Aug 11 01:51:35 CDT 1998 * SYNOPSIS:  MacOS X Server (Rhapsody Developer Release 2) * DESCRIPTION: *	MacOS X Server (Rhapsody Developer Release 2) * * CFLAGS: -DHAVE_STRERROR * TERMCAP: none * MATH: none *//* * normal stuff */#include <stdio.h>#include <stdarg.h>#include <errno.h>#include "top.h"#include "machine.h"#include "utils.h"/* * MacOS kernel stuff */#include <kvm.h>#include <fcntl.h>#include <sys/dkstat.h>#include <sys/sysctl.h>#include <mach/message.h>#include <mach/vm_statistics.h>#include <mach/mach.h>#define VMUNIX		"/mach_kernel"#define MEM		"/dev/mem"#define SWAP		NULL#define NUM_AVERAGES	3#define LOG1024		10#define MAX_COLS	128#define PP(pp, field)	((pp)->kp_proc . field)#define EP(pp, field)	((pp)->kp_eproc . field)#define VP(pp, field)	((pp)->kp_eproc.e_vm . field)#define MPP(mp, field)	(PP((mp)->kproc, field))#define MEP(mp, field)	(EP((mp)->kproc, field))#define MVP(mp, field)	(VP((mp)->kproc, field))#define TP(mp, field)	((mp)->task_info . field)#define RP(mp, field)	((mp)->thread_summary . field)/* define what weighted cpu is */#define weighted_cpu(pct, s) (s == 0 ? 0.0 : \                         ((pct) / (1.0 - exp(s * logcpu)))) /* what we consider to be process size: */#define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))#define TASKSIZE(t) (TP(t, virtual_size) + TP(t, resident_size))#define pctdouble(p) ((double)(p) / FSCALE)/* * globals */static kvm_t		*kd = NULL;static int		nproc;static int		onproc = -1;static int		pref_len;static long		maxmem;static long		hz;static char		fmt[MAX_COLS];static double		logcpu = 1.0;/* process array stuff */static struct kinfo_proc	*kproc_list = NULL;static struct macos_proc	*proc_list = NULL;static struct macos_proc	**proc_ref = NULL;static int			process_states[7];static struct handle		handle;/* * The mach information hopefully will not be necessary * when the kvm_* interfaces are supported completely. * * Since we're only concerned with task and thread info * for 'interesting' processes, we're going to only allocate * as many task and thread structures as needed. */static struct task_basic_info	*task_list = NULL;/* memory statistics */static int 		pageshift 	= 0;static int		pagesize	= 0;#define pagetok(size)	((size) << pageshift)static int		swappgsin	= -1;static int		swappgsout	= -1;static vm_statistics_data_t	vm_stats;static int		memory_stats[7];/* CPU state percentages */static long		cp_time[CPUSTATES];static long		cp_old[CPUSTATES];static long		cp_diff[CPUSTATES];static int		cpu_states[CPUSTATES];/* * types */typedef long 		pctcpu;//struct statics//{//	char	**procstate_names;//	char	**cpustate_names;//	char	**memory_names;//	char	**order_names;//};////struct system_info//{//	int	last_pid;//	double	load_avg[NUM_AVERAGES];//	int	p_total;	/* total # of processes *///	int	p_active;	/* number processes considered active *///	int	*procstates;//	int	*cpustates;//	int	*memory;//};////struct process_select//{//	int	idle;		/* show idle processes *///	int	system;		/* show system processes *///	int	uid;		/* show only this uid (unless -1) *///	char	*command;	/* only this command (unless NULL) *///};/* * We need to declare a hybrid structure which will store all * of the stuff we care about for each process. */struct macos_proc{	struct kinfo_proc		*kproc;	task_t				the_task;	struct task_basic_info		task_info;	int				thread_count;	struct thread_basic_info	thread_summary;};struct handle{	struct macos_proc		**next_proc;	int				remaining;};static char header[] =  "  PID X        PRI THRD  SIZE   RES STATE   TIME    MEM    CPU COMMAND";/* 0123456   -- field to fill in starts at header+6 */#define UNAME_START 6     #define Proc_format \        "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s"/* * puke() * * This function is used to report errors to stderr. */static void puke(const char* fmt, ...){	va_list	args;	va_start(args, fmt);	vfprintf(stderr, fmt, args);	va_end(args);	fputc('\n', stderr);	fflush(stderr);}/* * kread() * * This function is a wrapper for the kvm_read() function * with the addition of a message parameter per kvm_open(). * * All other behavior is per kvm_read except the error reporting. */static ssize_t kread(u_long addr, void *buf, 	size_t nbytes, const char *errstr){	ssize_t	s = 0;	s = kvm_read(kd, addr, buf, nbytes);	if(s == -1)		{		puke("error:  kvm_read() failed for '%s' (%s)\n",			errstr, strerror(errno));		}	return s;}/* * prototypes for functions which top needs */char *format_header(register char *uname_field);char *format_next_process(caddr_t handle, char *(*getuserid)());caddr_t get_process_info(struct system_info *si, struct process_select *sel, int (*compare)());int get_system_info(struct system_info *si);int machine_init(struct statics *stat);char *printable();/* * definitions for offsets */#define X_NPROC		0#define X_CP_TIME	1#define X_HZ		2#define X_MAXMEM	3#define NLIST_LAST	4static struct nlist	nlst[] ={	{ "_maxproc" },		/* 0 *** maximum processes */	{ "_cp_time" },		/* 1 */	{ "_hz" },		/* 2 */	{ "_mem_size" },	/* 3 */	{ 0 }};static char *procstates[] ={	"",	" starting, ",	" running, ",	" sleeping, ",	" stopped, ",	" zombie, ",	" swapped ",	NULL};static char *cpustates[] ={	"user",	"nice",	"system",	"intr",	"idle",	NULL};static char *state_abbrev[] ={	"",	"start",	"run\0\0\0",	"sleep",	"stop",	"zomb"};static char *mach_state[] ={	"",	"R",	"T",	"S",	"U",	"H"};static char *thread_state[] ={	"",	"run\0\0\0",	"stop",	"wait",	"uwait",	"halted",};static char *flags_state[] ={	"",	"W",	"I"};static char *memnames[] ={	"K Tot, ",	"K Free, ",	"K Act, ",	"K Inact, ",	"K Wired, ",	"K in, ",	"K out ",	NULL};/* * format_header() * * This function is used to add the username into the * header information. */char *format_header(register char *uname_field){	register char *ptr;	ptr = header + UNAME_START;	while(*uname_field != NULL)		*ptr++ = *uname_field++;	return(header);}/* * format_next_process() * * This function actuall is responsible for the formatting of * each row which is displayed. */char *format_next_process(caddr_t handle, char *(*getuserid)()){	register struct macos_proc	*pp;	register long			cputime;	register double			pct;	register int			vsize;	register int			rsize;	struct handle			*hp;	/*	 * we need to keep track of the next proc structure.	 */	hp = (struct handle*)handle;	pp = *(hp->next_proc++);	hp->remaining--;	/*	 * get the process structure and take care of the cputime	 */	if((MPP(pp, p_flag) & P_INMEM) == 0)		{		/* we want to print swapped processes as <pname> */		char	*comm = MPP(pp, p_comm);#define COMSIZ	sizeof(MPP(pp, p_comm))		char	buf[COMSIZ];		strncpy(buf, comm, COMSIZ);		comm[0] = '<';		strncpy(&comm[1], buf, COMSIZ - 2);		comm[COMSIZ - 2] = '\0';		strncat(comm, ">", COMSIZ - 1);		comm[COMSIZ - 1] = '\0';		}	/*	 * count the cpu time, but ignore the interrupts	 *	 * At the present time (DR2 8/1998), MacOS X doesn't	 * correctly report this information through the	 * kinfo_proc structure.  We need to get it from the	 * task threads.	 *	 * cputime = PP(pp, p_rtime).tv_sec;	 */		cputime = RP(pp, user_time).seconds + RP(pp, system_time).seconds;	/*	 * calculate the base cpu percentages	 *	 * Again, at the present time, MacOS X doesn't report	 * this information through the kinfo_proc.  We need	 * to talk to the threads.	 *///	pct = pctdouble(PP(pp, p_pctcpu));	pct = (double)(RP(pp, cpu_usage))/TH_USAGE_SCALE;	/*	 * format the entry	 */	/*	 * In the final version, I would expect this to work correctly,	 * but it seems that not all of the fields in the proc	 * structure are being used.	 *	 * For now, we'll attempt to get some of the things we need	 * from the mach task info.	 */	sprintf(fmt,		Proc_format,		MPP(pp, p_pid),		(*getuserid)(MEP(pp, e_pcred.p_ruid)),		TP(pp, base_priority),		pp->thread_count,		format_k(TASKSIZE(pp) / 1024),		format_k(pagetok((MVP(pp, vm_rssize)))),		state_abbrev[(u_char)MPP(pp, p_stat)],		format_time(cputime),		100.0 * TP(pp, resident_size) / maxmem,//		100.0 * weighted_cpu(pct, (RP(pp, user_time).seconds + RP(pp, system_time).seconds)),		100.0 * pct,		printable(MPP(pp, p_comm)));	return(fmt);}/* * get_process_info() * * This function returns information about the processes * on the system. */caddr_t get_process_info(struct system_info *si,		struct process_select *sel, int (*compare)()){	register int 				i;	register int 				total_procs;	register int 				active_procs;	register struct macos_proc 		**prefp;	register struct macos_proc 		*pp;	register struct kinfo_proc		*pp2;	register struct kinfo_proc		**prefp2;	register struct thread_basic_info 	*thread;	/*	 * these are copied out of sel for speed	 */	int show_idle;	int show_system;	int show_uid;	int show_command;	kproc_list = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);	if(nproc > onproc)		{		proc_list = (struct macos_proc*)realloc(proc_list, sizeof(struct macos_proc) * nproc);		proc_ref = (struct macos_proc **)realloc(proc_ref, sizeof(struct macos_proc *) * (onproc = nproc));		}	if(proc_ref == NULL || proc_list == NULL || kproc_list == NULL)		{		puke("error:  out of memory (%s)", strerror(errno));		return(NULL);		}	/*	 * now, our task is to build the array of information we	 * need to function correctly.  This involves setting a pointer	 * to each real kinfo_proc structure returned by kvm_getprocs()	 * in addition to getting the mach information for each of	 * those processes.	 */	for(pp2 = kproc_list, i = 0; i < nproc; pp2++, i++)		{		kern_return_t	rc;		u_int		info_count = TASK_BASIC_INFO_COUNT;		/*

⌨️ 快捷键说明

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