📄 m_next32.c
字号:
{ pref[j].p_self = pp; if(thread_status==KERN_SUCCESS) { pref[j].run_state = threadInfo.run_state; pref[j].flags = threadInfo.flags; pref[j].p_pctcpu = threadInfo.cpu_usage; pref[j].p_cptime = threadInfo.user_time.seconds + threadInfo.system_time.seconds; pref[j].cur_priority = threadInfo.cur_priority; pref[j].nthreads = threadCount; } else { pref[j].run_state = 0; pref[j].flags = 0; pref[j].p_pctcpu = 0; pref[j].p_cptime = 0; } /* Get processes memory usage and cputime */ if(task_status==KERN_SUCCESS) { pref[j].p_rsize = taskInfo.resident_size/1024; pref[j].p_vsize = taskInfo.virtual_size/1024; } else { pref[j].p_rsize = 0; pref[j].p_vsize = 0; } active_procs++; j++; } } i++; } while(pp->p_nxt != 0); pref[j].p_self = NULL; /* End list of processes with NULL */ /* if requested, sort the "interesting" processes */ if (compare != NULL) { qsort((char *)pref, active_procs, sizeof(struct proc_unix), compare); } /* remember active and total counts */ si->p_total = total_procs; si->p_active = pref_count = active_procs; /* pass back a handle */ handle.list = pref; handle.count = active_procs; handle.current = 0; 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 proc *pp; register long cputime; register double pct, wcpu, pctmem; int where; struct user u; struct handle *hp; register int p_pctcpu; register int rm_size; register int vm_size; register int run_state; register int flags; register int nthreads; register int cur_priority; char state_str[10]; /* find and remember the next proc structure */ hp = (struct handle *)handle; pp = hp->list[hp->current].p_self; p_pctcpu = hp->list[hp->current].p_pctcpu; cputime = hp->list[hp->current].p_cptime; rm_size = hp->list[hp->current].p_rsize; vm_size = hp->list[hp->current].p_vsize; run_state = hp->list[hp->current].run_state; flags = hp->list[hp->current].flags; nthreads = hp->list[hp->current].nthreads; cur_priority = hp->list[hp->current].cur_priority; hp->current++; hp->count--; /* get the process's user struct and set cputime */ where = getu(pp, &u); if (where == -1) { (void) strcpy(u.u_comm, "<swapped>"); cputime = 0; } else { /* set u_comm for system processes */ if (u.u_comm[0] == '\0') { if (pp->p_pid == 0) { (void) strcpy(u.u_comm, "Swapper"); } else if (pp->p_pid == 2) { (void) strcpy(u.u_comm, "Pager"); } } if (where == 1) { /* * Print swapped processes as <pname> */ char buf[sizeof(u.u_comm)]; (void) strncpy(buf, u.u_comm, sizeof(u.u_comm)); u.u_comm[0] = '<'; (void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2); u.u_comm[sizeof(u.u_comm) - 2] = '\0'; (void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1); u.u_comm[sizeof(u.u_comm) - 1] = '\0'; }/* User structure does not work. Use Thread Info to get cputime for process. *//* cputime = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec; */ } /* calculate the base for cpu percentages */ pct = (double)(p_pctcpu)/TH_USAGE_SCALE;/* wcpu = weighted_cpu(pct, pp); */ pctmem = (double)(rm_size*1024.) / (double)(host_stats.memory_size); /* Get process state description */ if(run_state) { strcpy(state_str, mach_state[run_state]); strcat(state_str, flags_state[flags]); } else { strcpy(state_str, state_abbrev[pp->p_stat]); } /* format this entry */ sprintf(fmt, Proc_format, pp->p_pid, (*get_userid)(pp->p_uid), state_str, cur_priority,/* pp->p_pri - PZERO, */ pp->p_nice - NZERO, nthreads, format_k(vm_size), format_k(rm_size), 100.0 * pctmem,/* 100.0 * wcpu, */ 100.0 * pct, format_time(cputime), printable(u.u_comm)); /* return the result */ return(fmt);}/* * getu(p, u) - get the user structure for the process whose proc structure * is pointed to by p. The user structure is put in the buffer pointed * to by u. Return 0 if successful, -1 on failure (such as the process * being swapped out). */getu(register struct proc *p, struct user *u){ register int nbytes, n; struct task task; struct utask utask; struct uthread thread; /* * Check if the process is currently loaded or swapped out. The way we * get the u area is totally different for the two cases. For this * application, we just don't bother if the process is swapped out. */ /* NEXTSTEP proc.h * One structure allocated per active * process. It contains all data needed * about the process while the * process may be swapped out. * Other per process data (user.h) * is swapped with the process. */ if ((p->p_flag & SLOAD) == 0) {/* User info is always in core. * #ifdef DOSWAP * if (lseek(swap, (long)dtob(p->p_swaddr), 0) == -1) { * perror("lseek(swap)"); * return(-1); * } * if (read(swap, (char *) u, sizeof(struct user)) != sizeof(struct user)) { * perror("read(swap)"); * return(-1); * } * return (1); * #else */ return(-1);/*#endif */ } /* * Process is currently in memory, we hope! */ if(!getkval(p->task, (int *)&task, sizeof(struct task), "task")) {#ifdef DEBUG perror("getkval(p->task)");#endif /* we can't seem to get to it, so pretend it's swapped out */ return(-1); } if(!getkval(task.u_address, (int *)&utask, sizeof(struct utask), "task.u_address")) {#ifdef DEBUG perror("getkval(task->utask)");#endif /* we can't seem to get to it, so pretend it's swapped out */ return(-1); } /* Copy utask and uthread info into struct user *u */ /* This is incomplete. Only copied info needed. */ u->u_procp = utask.uu_procp; u->u_ar0 = utask.uu_ar0; u->u_ru = utask.uu_ru; strcpy(u->u_comm, utask.uu_comm); nbytes = strlen(u->u_comm); for(n=nbytes; n<MAXCOMLEN; n++) u->u_comm[n] = ' '; u->u_comm[MAXCOMLEN] = '\0'; return(0);}/* * 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. */int check_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_un.n_name != NULL) { if (nlst->n_type == 0 && nlst->n_value == 0) { /* this one wasn't found */ fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_un.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). * */getkval(unsigned long offset, int *ptr, int size, char *refstr){ if (lseek(kmem, (long)offset, L_SET) == -1) { if (*refstr == '!') refstr++; (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM, refstr, strerror(errno)); quit(23); } if (read(kmem, (char *) ptr, size) == -1) { if (*refstr == '!') return(0); else { (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM, refstr, strerror(errno)); quit(23); } } return(1);} /* comparison routine for qsort *//* * proc_compare - comparison function for "qsort" * Compares the resource consumption of two processes using five * distinct keys. The keys (in descending order of importance) are: * percent cpu, cpu ticks, 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. */static unsigned char sorted_state[] ={ 0, /* not used */ 3, /* sleep */ 1, /* ABANDONED (WAIT) */ 6, /* run */ 5, /* start */ 2, /* zombie */ 4 /* stop */}; proc_compare(struct proc_unix *pp1, struct proc_unix *pp2){ register struct proc *p1 = pp1->p_self; register struct proc *p2 = pp2->p_self; register int result; register pctcpu lresult; /* compare percent cpu (pctcpu) */ if ((lresult = pp2->p_pctcpu - pp1->p_pctcpu) == 0) { /* use cpticks to break the tie */ if ((result = P_CPTICKS(p2) - P_CPTICKS(p1)) == 0) { /* use process state to break the tie */ if ((result = sorted_state[p2->p_stat] - sorted_state[p1->p_stat]) == 0) { /* use priority to break the tie */ if ((result = p2->p_pri - p1->p_pri) == 0) { /* use resident set size (rssize) to break the tie */ if ((result = pp2->p_rsize - pp1->p_rsize) == 0) { /* use total memory to break the tie */ result = pp2->p_vsize - pp1->p_vsize; } } } } } else { result = lresult < 0 ? -1 : 1; } return(result);}/* * proc_owner(pid) - returns the uid that owns process "pid", or -1 if * the process does not exist. * It is EXTREMLY IMPORTANT that this function work correctly. * If top runs setuid root (as in SVR4), then this function * is the only thing that stands in the way of a serious * security problem. It validates requests for the "kill" * and "renice" commands. */int proc_owner(int pid){ register int cnt; register struct proc *pp; cnt = pref_count; while (--cnt >= 0) { pp = pref[cnt].p_self; if( pp->p_pid == pid ) /* Modified (pid_t)pid to pid, compiler error. */ { return((int)pp->p_uid); } } return(-1);}int thread_stats(int pid, struct thread_basic_info *info, int *thread_count){ int i; kern_return_t status; kern_return_t status_dealloc; task_t p_task; thread_array_t thread_list, list; struct thread_basic_info threadInfo; unsigned int info_count = THREAD_BASIC_INFO_COUNT; /* Get the task pointer for the process. */ status = task_by_unix_pid( task_self(), pid, &p_task); if (status!=KERN_SUCCESS) {#ifdef DEBUG printf("pid = %i\n", pid); mach_error("Error calling task_by_unix_pid()", status);#endif return status; } /* Get the list of threads for the task. */ status = task_threads(p_task, &thread_list, thread_count); if (status!=KERN_SUCCESS) {#ifdef DEBUG mach_error("Error calling task_threads()", status);#endif return status; } /* Get the pctcpu value for each thread and sum the values */ info->user_time.seconds = 0; info->user_time.microseconds = 0; info->system_time.seconds = 0; info->system_time.microseconds = 0; info->cpu_usage = 0; info->sleep_time = 0; for(i=0; i<*thread_count; i++) { status = thread_info(thread_list[i], THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &info_count); if (status!=KERN_SUCCESS) {#ifdef DEBUG mach_error("Error calling thread_info()", status);#endif break; } else { if(i==0) { info->base_priority = threadInfo.base_priority; info->cur_priority = threadInfo.cur_priority; info->run_state = threadInfo.run_state; info->flags = threadInfo.flags; info->suspend_count = threadInfo.suspend_count; info->sleep_time += threadInfo.sleep_time; } info->user_time.seconds += threadInfo.user_time.seconds; info->user_time.microseconds += threadInfo.user_time.microseconds; info->system_time.seconds += threadInfo.system_time.seconds; info->system_time.microseconds += threadInfo.system_time.microseconds; info->cpu_usage += threadInfo.cpu_usage; } } /* Deallocate the list of threads. */ status_dealloc = vm_deallocate(task_self(), (vm_address_t)thread_list, sizeof(thread_list)*(*thread_count)); if (status_dealloc != KERN_SUCCESS) {#ifdef DEBUG mach_error("Trouble freeing thread_list", status_dealloc);#endif status = status_dealloc; } return status;}int mach_load_avg(void){ kern_return_t status; host_t host; unsigned int info_count; struct processor_set_basic_info info; processor_set_t default_set; status=processor_set_default(host_self(), &default_set); if (status!=KERN_SUCCESS){ mach_error("Error calling processor_set_default", status); exit(1); } info_count=PROCESSOR_SET_BASIC_INFO_COUNT; status=processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, &host, (processor_set_info_t)&info, &info_count);#ifdef DEBUG if (status != KERN_SUCCESS) mach_error("Error calling processor_set_info", status);#endif return info.load_average;}kern_return_t task_stats(int pid, struct task_basic_info *info){ kern_return_t status; task_t p_task; unsigned int info_count=TASK_BASIC_INFO_COUNT; /* Get the task pointer for the process. */ status = task_by_unix_pid( task_self(), pid, &p_task); if (status!=KERN_SUCCESS) {#ifdef DEBUG printf("pid = %i\n", pid); mach_error("Error calling task_by_unix_pid()", status);#endif return(status); } status=task_info(p_task, TASK_BASIC_INFO, (task_info_t)info, &info_count); if (status!=KERN_SUCCESS) {#ifdef DEBUG mach_error("Error calling task_info()", status);#endif return(status); } return(KERN_SUCCESS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -