📄 machine.c
字号:
goto kcid_changed;int kupdate(int avenrun[3]){ kstat_t *ks; kid_t nkcid; int i; int changed = 0; static int ncpu = 0; static kid_t kcid = 0; kstat_named_t *kn; /* * 0. kstat_open */ if (!kc) { kc = kstat_open(); if (!kc) { perror("kstat_open "); quit(1); } changed = 1; kcid = kc->kc_chain_id; } /* keep doing it until no more changes */ kcid_changed: /* * 1. kstat_chain_update */ nkcid = kstat_chain_update(kc); if (nkcid) { /* UPDKCID will abort if nkcid is -1, so no need to check */ changed = 1; kcid = nkcid; } UPDKCID(nkcid,0); ks = kstat_lookup(kc, "unix", 0, "system_misc"); if (kstat_read(kc, ks, 0) == -1) { perror("kstat_read"); quit(1); } /* load average */ kn = kstat_data_lookup(ks, "avenrun_1min"); if (kn) avenrun[0] = kn->value.ui32; kn = kstat_data_lookup(ks, "avenrun_5min"); if (kn) avenrun[1] = kn->value.ui32; kn = kstat_data_lookup(ks, "avenrun_15min"); if (kn) avenrun[2] = kn->value.ui32; /* nproc */ kn = kstat_data_lookup(ks, "nproc"); if (kn) { nproc = kn->value.ui32;#ifdef NO_NPROC if (nproc > maxprocs) reallocproc(2 * nproc);#endif } if (changed) { /* * 2. get data addresses */ ncpu = 0; kn = kstat_data_lookup(ks, "ncpus"); if (kn && kn->value.ui32 > ncpus) { ncpus = kn->value.ui32; cpu_ks = (kstat_t **) realloc (cpu_ks, ncpus * sizeof (kstat_t *)); cpu_stat = (cpu_stat_t *) realloc (cpu_stat, ncpus * sizeof (cpu_stat_t)); } for (ks = kc->kc_chain; ks; ks = ks->ks_next) { if (strncmp(ks->ks_name, "cpu_stat", 8) == 0) { nkcid = kstat_read(kc, ks, NULL); /* if kcid changed, pointer might be invalid */ UPDKCID(nkcid, kcid); cpu_ks[ncpu] = ks; ncpu++; if (ncpu > ncpus) { fprintf(stderr, "kstat finds too many cpus: should be %d\n", ncpus); quit(1); } } } /* note that ncpu could be less than ncpus, but that's okay */ changed = 0; } /* * 3. get data */ for (i = 0; i < ncpu; i++) { nkcid = kstat_read(kc, cpu_ks[i], &cpu_stat[i]); /* if kcid changed, pointer might be invalid */ UPDKCID(nkcid, kcid); } /* return the number of cpus found */ return(ncpu);}#endif /* USE_KSTAT */voidget_system_info (struct system_info *si){ int avenrun[3]; static int freemem; static int maxmem; static int availrmem; static int swapfs_minfree; static int swap_total; static int swap_free; struct anoninfo anoninfo; static long cp_time[CPUSTATES]; static long cp_old[CPUSTATES]; static long cp_diff[CPUSTATES]; register int j, i;#ifdef USE_KSTAT kstat_t *ks; kstat_named_t *kn; int cpus_found;#else struct cpu cpu;#endif /* get the cp_time array */ for (j = 0; j < CPUSTATES; j++) cp_time[j] = 0L;#ifdef USE_KSTAT /* use kstat to upadte all processor information */ cpus_found = kupdate(avenrun); for (i = 0; i < cpus_found; i++) { /* sum counters up to, but not including, wait state counter */ for (j = 0; j < CPU_WAIT; j++) cp_time[j] += (long) cpu_stat[i].cpu_sysinfo.cpu[j]; /* add in wait state breakdown counters */ cp_time[CPUSTATE_IOWAIT] += (long) cpu_stat[i].cpu_sysinfo.wait[W_IO] + (long) cpu_stat[i].cpu_sysinfo.wait[W_PIO]; cp_time[CPUSTATE_SWAP] += (long) cpu_stat[i].cpu_sysinfo.wait[W_SWAP]; } /* avenrun */#if OSREV >= 55 ks = kstat_lookup(kc, "unix", 0, "system_pages"); if (kstat_read(kc, ks, 0) == -1) { perror("kstat_read"); quit(1); }#ifdef USE_ANONINFO kn = kstat_data_lookup(ks, "availrmem"); if (kn) availrmem = kn->value.ul;#endif kn = kstat_data_lookup(ks, "freemem"); if (kn) freemem = kn->value.ul;#endif /* OSREV >= 55 */#else /* !USE_KSTAT */ for (i = 0; i < ncpus; i++) if (cpu_offset[i] != 0) { /* get struct cpu for this processor */ (void) getkval (cpu_offset[i], &cpu, sizeof (struct cpu), "cpu"); /* sum counters up to, but not including, wait state counter */ for (j = 0; j < CPU_WAIT; j++) cp_time[j] += (long) cpu.cpu_stat.cpu_sysinfo.cpu[j]; /* add in wait state breakdown counters */ cp_time[CPUSTATE_IOWAIT] += (long) cpu.cpu_stat.cpu_sysinfo.wait[W_IO] + (long) cpu.cpu_stat.cpu_sysinfo.wait[W_PIO]; cp_time[CPUSTATE_SWAP] += (long) cpu.cpu_stat.cpu_sysinfo.wait[W_SWAP]; } /* get load average array */ (void) getkval (avenrun_offset, (int *) avenrun, sizeof (avenrun), "avenrun");#endif /* USE_KSTAT */ /* convert cp_time counts to percentages */ (void) percentages (CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); /* get mpid -- process id of last process */ if (kd) (void) getkval(mpid_offset, &(si->last_pid), sizeof (si->last_pid), "mpid"); else si->last_pid = -1; /* convert load averages to doubles */ for (i = 0; i < 3; i++) si->load_avg[i] = loaddouble (avenrun[i]); /* get system wide main memory usage structure */#if 1 maxmem = sysconf(_SC_PHYS_PAGES);#else (void) getkval (maxmem_offset, (int *) (&maxmem), sizeof (maxmem), "maxmem");#endif#if !defined(USE_KSTAT) || OSREV < 55 (void) getkval (freemem_offset, (int *) (&freemem), sizeof (freemem), "freemem");#endif memory_stats[0] = pagetok (maxmem); memory_stats[1] = 0; memory_stats[2] = pagetok (freemem);#ifdef USE_ANONINFO (void) getkval (anoninfo_offset, (int *) (&anoninfo), sizeof (anoninfo), "anoninfo");#if !defined(USE_KSTAT) || OSREV < 55 (void) getkval (availrmem_offset, (int *) (&availrmem), sizeof (availrmem), "availrmem");#endif (void) getkval (swapfs_minfree_offset, (int *) (&swapfs_minfree), sizeof (swapfs_minfree), "swapfs_minfree"); memory_stats[3] = pagetok (anoninfo.ani_resv); memory_stats[4] = pagetok (MAX ((int) (anoninfo.ani_max - anoninfo.ani_resv), 0) + availrmem - swapfs_minfree);#else get_swapinfo(&swap_total, &swap_free); memory_stats[3] = pagetok(swap_total - swap_free); memory_stats[4] = pagetok(swap_free);#endif /* set arrays and strings */ si->cpustates = cpu_states; si->memory = memory_stats;}static struct handle handle;caddr_tget_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 prpsinfo **prefp; register struct prpsinfo *pp; /* these are copied out of sel for speed */ int show_idle; int show_system; int show_uid;#ifndef USE_KSTAT /* Get current number of processes */ /* Got this when calling system info if using kstat */ (void) getkval (nproc_offset, (int *) (&nproc), sizeof (nproc), "nproc");#endif /* read all the proc structures */ getptable (pbase); /* get a pointer to the states summary array */ si->procstates = process_states; /* set up flags which define what we are going to select */ show_idle = sel->idle; show_system = sel->system; show_uid = sel->uid != -1; /* count up process states and get pointers to interesting procs */ total_procs = 0; active_procs = 0; (void) memset (process_states, 0, sizeof (process_states)); prefp = pref; for (pp = pbase, i = 0; i < nproc; i++, pp = (struct prpsinfo *) ((char *) pp + PRPSINFOSIZE)) { /* * Place pointers to each valid proc structure in pref[]. * Process slots that are actually in use have a non-zero * status field. Processes with SSYS set are system * processes---these get ignored unless show_sysprocs is set. */ if (pp->pr_state != 0 && (show_system || ((pp->pr_flag & SSYS) == 0))) { total_procs++; process_states[pp->pr_state]++; if ((!ZOMBIE(pp)) && (show_idle || percent_cpu (pp) || (pp->pr_state == SRUN) || (pp->pr_state == SONPROC)) && (!show_uid || pp->pr_uid == (uid_t) sel->uid)) { *prefp++ = pp; active_procs++; } } } /* if requested, sort the "interesting" processes */ if (compare != NULL) qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *), compare); /* remember active and total counts */ si->p_total = total_procs; si->p_active = active_procs; /* pass back a handle */ handle.next_proc = pref; handle.remaining = active_procs; return ((caddr_t) & handle);}char fmt[MAX_COLS]; /* static area where result is built */char *format_next_process ( caddr_t handle, char *(*get_userid) ()){ register struct prpsinfo *pp; struct handle *hp; register long cputime; register double pctcpu; char sb[10]; /* find and remember the next proc structure */ hp = (struct handle *) handle; pp = *(hp->next_proc++); hp->remaining--; /* get the cpu usage and calculate the cpu percentages */ cputime = pp->pr_time.tv_sec; pctcpu = percent_cpu (pp); if (pp->pr_state == SONPROC && ncpus > 1) sprintf(sb,"cpu%-2d", pp->pr_onpro); /* XXX large #s may overflow colums */ else *sb = '\0'; /* format this entry */ sprintf (fmt, Proc_format, pp->pr_pid, (*get_userid) (pp->pr_uid), (u_short)pp->pr_fill < 999 ? (u_short)pp->pr_fill : 999, pp->pr_pri, pp->pr_nice - NZERO, format_k(SIZE_K(pp)), format_k(RSS_K(pp)), *sb ? sb : state_abbrev[pp->pr_state], format_time(cputime), pctcpu, pp->pr_fname); /* return the result */ return (fmt);}/* * check_nlist(nlst) - checks the nlist to see if any symbols were not * found. For every symbol that was not found, a one-line * message is printed to stderr. The routine returns the * number of symbols NOT found. */intcheck_nlist (register struct nlist *nlst){ register int i; /* check to see if we got ALL the symbols we requested */ /* this will write one line to stderr for every symbol not found */ i = 0; while (nlst->n_name != NULL) { if (nlst->n_type == 0) { /* this one wasn't found */ fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name); i = 1; } nlst++; } return (i);}/* * getkval(offset, ptr, size, refstr) - get a value out of the kernel. * "offset" is the byte offset into the kernel for the desired value, * "ptr" points to a buffer into which the value is retrieved, * "size" is the size of the buffer (and the object to retrieve), * "refstr" is a reference string used when printing error meessages, * if "refstr" starts with a '!', then a failure on read will not * be fatal (this may seem like a silly way to do things, but I * really didn't want the overhead of another argument). * */intgetkval (unsigned long offset, int *ptr, int size, char *refstr){ if (kvm_read (kd, offset, (char *) ptr, size) != size) { if (*refstr == '!') { return (0); } else { fprintf (stderr, "top: kvm_read for %s: %s\n", refstr, strerror(errno)); quit (23); } } return (1);}/* comparison routines for qsort *//* * There are currently four possible comparison routines. main selects * one of these by indexing in to the array proc_compares. * * Possible keys are defined as macros below. Currently these keys are * defined: percent cpu, cpu ticks, process state, resident set size, * total virtual memory usage. The process states are ordered as follows * (from least to most important): WAIT, zombie, sleep, stop, start, run. * The array declaration below maps a process state index into a number * that reflects this ordering. *//* First, the possible comparison keys. These are defined in such a way that they can be merely listed in the source code to define the actual desired ordering. */#define ORDERKEY_PCTCPU if (dresult = percent_cpu (p2) - percent_cpu (p1),\ (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)#define ORDERKEY_CPTICKS if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)#define ORDERKEY_STATE if ((result = (long) (sorted_state[p2->pr_state] - \ sorted_state[p1->pr_state])) == 0)#define ORDERKEY_PRIO if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0)#define ORDERKEY_RSSIZE if ((result = p2->pr_rssize - p1->pr_rssize) == 0)#define ORDERKEY_MEM if ((result = (p2->pr_size - p1->pr_size)) == 0)/* Now the array that maps process state to a weight */unsigned char sorted_state[] ={ 0, /* not used */ 3, /* sleep */ 6, /* run */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -