📄 m_macosx.c
字号:
* first, we set the pointer to the reference in * the kproc list. */ proc_list[i].kproc = pp2; /* * then, we load all of the task info for the process */ if(PP(pp2, p_stat) != SZOMB) { rc = task_by_unix_pid(task_self(), PP(pp2, p_pid), &(proc_list[i].the_task)); if(rc != KERN_SUCCESS) { puke("error: get task info for pid %d failed with rc = %d", PP(pp2, p_pid), rc); } /* * load the task information */ rc = task_info(proc_list[i].the_task, TASK_BASIC_INFO, (task_info_t)&(proc_list[i].task_info), &info_count); if(rc != KERN_SUCCESS) { puke("error: couldn't get task info (%s); rc = %d", strerror(errno), rc); } /* * load the thread summary information */ load_thread_info(&proc_list[i]); } } /* 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; show_command = sel->command != NULL; /* count up process states and get pointers to interesting procs */ total_procs = 0; active_procs = 0; memset((char *)process_states, 0, sizeof(process_states)); prefp = proc_ref; for(pp = proc_list, i = 0; i < nproc; pp++, i++) { /* * Place pointers to each valid proc structure in * proc_ref[]. Process slots that are actually in use * have a non-zero status field. Processes with * P_SYSTEM set are system processes---these get * ignored unless show_sysprocs is set. */ if(MPP(pp, p_stat) != 0 && (show_system || ((MPP(pp, p_flag) & P_SYSTEM) == 0))) { total_procs++; process_states[(unsigned char) MPP(pp, p_stat)]++; if((MPP(pp, p_stat) != SZOMB) && (show_idle || (MPP(pp, p_pctcpu) != 0) || (MPP(pp, p_stat) == SRUN)) && (!show_uid || MEP(pp, e_pcred.p_ruid) == (uid_t)sel->uid)) { *prefp++ = pp; active_procs++; } } } /* * if requested, sort the "interesting" processes */ if(compare != NULL) qsort((char *)proc_ref, active_procs, sizeof(struct macos_proc *), compare); /* remember active and total counts */ si->p_total = total_procs; si->p_active = pref_len = active_procs; /* pass back a handle */ handle.next_proc = proc_ref; handle.remaining = active_procs; return((caddr_t)&handle);}/* * get_system_info() * * This function is responsible for geting the periodic * system information snapshot. */int get_system_info(struct system_info *si){ register long total; register int i; /* * get the cp_time array */ if(!kread(nlst[X_CP_TIME].n_value, cp_time, sizeof(cp_time), nlst[X_CP_TIME].n_name)) return(0);#ifdef MAX_VERBOSE /* * print out the entries */ for(i = 0; i < CPUSTATES; i++) printf("cp_time[%d] = %d\n", i, cp_time[i]);#endif /* MAX_VERBOSE */ /* * get the load averages */ if(kvm_getloadavg(kd, si->load_avg, NUM_AVERAGES) == -1) { puke("error: kvm_getloadavg() failed (%s)", strerror(errno)); return(0); }#ifdef MAX_VERBOSE printf("%-30s%03.2f, %03.2f, %03.2f\n", "load averages:", si->load_avg[0], si->load_avg[1], si->load_avg[2]);#endif /* MAX_VERBOSE */ total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); /* * get the memory statistics */ { kern_return_t status; status = vm_statistics(task_self(), &vm_stats); if(status != KERN_SUCCESS) { puke("error: vm_statistics() failed (%s)", strerror(errno)); return(0); } /* * we already have the total memory, we just need * to get it in the right format. */ memory_stats[0] = pagetok(maxmem / vm_stats.pagesize); memory_stats[1] = pagetok(vm_stats.free_count); memory_stats[2] = pagetok(vm_stats.active_count); memory_stats[3] = pagetok(vm_stats.inactive_count); memory_stats[4] = pagetok(vm_stats.wire_count); if(swappgsin < 0) { memory_stats[5] = 1; memory_stats[6] = 1; } else { memory_stats[5] = pagetok(((vm_stats.pageins - swappgsin))); memory_stats[6] = pagetok(((vm_stats.pageouts - swappgsout))); } swappgsin = vm_stats.pageins; swappgsout = vm_stats.pageouts; } si->cpustates = cpu_states; si->memory = memory_stats; si->last_pid = -1; return(1);}/* * machine_init() * * This function is responsible for filling in the values of the * statics structure. */int machine_init(struct statics *stat){ register int rc = 0; register int i = 0;// register int pagesize; /* * open the kernel */ if((kd = kvm_open(VMUNIX, MEM, SWAP, O_RDONLY, "kvm_open")) == NULL) { puke("error: couldn't open kernel (%s)", strerror(errno)); return(0); } /* * turn off super-user privs */// seteuid(getuid()); /* * read the nlist we need */ rc = kvm_nlist(kd, nlst); if(rc == -1) { puke("error: unable to read kernel table (%s)", strerror(errno)); return(0); } if(rc > 0) { puke("error: kvm_nlist() found %d invalid entries.\n", rc); return(0); }#ifdef MAX_VERBOSE /* * print out the entries */ for(i = 0; i < NLIST_LAST; i++) { printf("symbol %10s is type 0x%02X at offset 0x%02X\n", nlst[i].n_name, nlst[i].n_type & N_TYPE, nlst[i].n_value); }#endif /* MAX_VERBOSE */ /* * next, we get the data for the names * * get max number of processes */ if(!kread(nlst[X_NPROC].n_value, &nproc, sizeof(nproc), nlst[X_NPROC].n_name)) return(0);#ifdef MAX_VERBOSE printf("%-30s%10d\n", "max number of processes:", nproc);#endif /* MAX_VERBOSE */ /* * get clock rate */ if(!kread(nlst[X_HZ].n_value, &hz, sizeof(hz), nlst[X_HZ].n_name)) return(0);#ifdef MAX_VERBOSE printf("%-30s%10d\n", "clock rate:", hz);#endif /* MAX_VERBOSE */ /* * get memory size */ if(!kread(nlst[X_MAXMEM].n_value, &maxmem, sizeof(maxmem), nlst[X_MAXMEM].n_name)) return(0);#ifdef MAX_VERBOSE printf("%-30s%10d\n", "total system memory:", maxmem);#endif /* MAX_VERBOSE */ /* * calculate the pageshift from the system page size */ pagesize = getpagesize(); pageshift = 0; while((pagesize >>= 1) > 0) pageshift++; pageshift -= LOG1024; /* * fill in the statics information */ stat->procstate_names = procstates; stat->cpustate_names = cpustates; stat->memory_names = memnames; return(0);}/* 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 */}; int proc_compare(struct macos_proc **pp1, struct macos_proc **pp2){ register struct macos_proc *p1; register struct macos_proc *p2; register int result; register pctcpu lresult; /* remove one level of indirection */ p1 = *(struct macos_proc **) pp1; p2 = *(struct macos_proc **) pp2; /* compare percent cpu (pctcpu) */ if ((lresult = RP(p2, cpu_usage) - RP(p1, cpu_usage)) == 0) { /* use cpticks to break the tie */ if ((result = MPP(p2, p_cpticks) - MPP(p1, p_cpticks)) == 0) { /* use process state to break the tie */ if ((result = sorted_state[(unsigned char) MPP(p2, p_stat)] - sorted_state[(unsigned char) MPP(p1, p_stat)]) == 0) { /* use priority to break the tie */ if ((result = MPP(p2, p_priority) - MPP(p1, p_priority)) == 0) { /* use resident set size (rssize) to break the tie */ if ((result = MVP(p2, vm_rssize) - MVP(p1, vm_rssize)) == 0) { /* use total memory to break the tie */ result = PROCSIZE(p2->kproc) - PROCSIZE(p1->kproc); } } } } } 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(pid)int pid;{ register int cnt; register struct macos_proc **prefp; register struct macos_proc *pp; prefp = proc_ref; cnt = pref_len; while (--cnt >= 0) { pp = *prefp++; if (MPP(pp, p_pid) == (pid_t)pid) { return((int)MEP(pp, e_pcred.p_ruid)); } } return(-1);}/* * load_thread_info() * * This function will attempt to load the thread summary info * for a Mach task. The task is located as part of the macos_proc * structure. * * returns the kern_return_t value of any failed call or KERN_SUCCESS * if everything works. */int load_thread_info(struct macos_proc *mp){ register kern_return_t rc = 0; register int i = 0; register int t_utime = 0; register int t_stime = 0; register int t_cpu = 0; register int t_state = 0; register task_t the_task = mp->the_task; thread_array_t thread_list = NULL; /* * We need to load all of the threads for the * given task so we can get the performance * data from them. */ mp->thread_count = 0; rc = task_threads(the_task, &thread_list, &(mp->thread_count)); if(rc != KERN_SUCCESS) {// puke("error: unable to load threads for task (%s); rc = %d", strerror(errno), rc); return(rc); } /* * now, for each of the threads, we need to sum the stats * so we can present the whole thing to the caller. */ for(i = 0; i < mp->thread_count; i++) { struct thread_basic_info t_info; int icount = THREAD_BASIC_INFO_COUNT; kern_return_t rc = 0; rc = thread_info(thread_list[i], THREAD_BASIC_INFO, (thread_info_t)&t_info, &icount); if(rc != KERN_SUCCESS) { puke("error: unable to load thread info for task (%s); rc = %d", strerror(errno), rc); return(rc); } t_utime += t_info.user_time.seconds; t_stime += t_info.system_time.seconds; t_cpu += t_info.cpu_usage; } vm_deallocate(task_self(), (vm_address_t)thread_list, sizeof(thread_array_t)*(mp->thread_count)); /* * Now, we load the values in the structure above. */ RP(mp, user_time).seconds = t_utime; RP(mp, system_time).seconds = t_stime; RP(mp, cpu_usage) = t_cpu; return(KERN_SUCCESS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -