version 1.36, 2003/07/07 21:36:52 |
version 1.37, 2004/01/08 18:15:06 |
|
|
/* get_process_info passes back a handle. This is what it looks like: */ |
/* get_process_info passes back a handle. This is what it looks like: */ |
|
|
struct handle { |
struct handle { |
struct kinfo_proc **next_proc; /* points to next valid proc pointer */ |
struct kinfo_proc2 **next_proc; /* points to next valid proc pointer */ |
int remaining; /* number of pointers remaining */ |
int remaining; /* number of pointers remaining */ |
}; |
}; |
|
|
#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) |
|
|
|
/* what we consider to be process size: */ |
/* what we consider to be process size: */ |
#define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize)) |
#define PROCSIZE(pp) ((pp)->p_vm_tsize + (pp)->p_vm_dsize + (pp)->p_vm_ssize) |
|
|
/* |
/* |
* These definitions control the format of the per-process area |
* These definitions control the format of the per-process area |
|
|
static int nproc; |
static int nproc; |
static int onproc = -1; |
static int onproc = -1; |
static int pref_len; |
static int pref_len; |
static struct kinfo_proc *pbase; |
static struct kinfo_proc2 *pbase; |
static struct kinfo_proc **pref; |
static struct kinfo_proc2 **pref; |
|
|
/* these are for getting the memory statistics */ |
/* these are for getting the memory statistics */ |
static int pageshift; /* log base 2 of the pagesize */ |
static int pageshift; /* log base 2 of the pagesize */ |
|
|
|
|
static struct handle handle; |
static struct handle handle; |
|
|
static struct kinfo_proc * |
static struct kinfo_proc2 * |
getprocs(int op, int arg, int *cnt) |
getprocs(int op, int arg, int *cnt) |
{ |
{ |
size_t size = sizeof(int); |
size_t size; |
int mib[4] = {CTL_KERN, KERN_PROC, 0, 0}; |
int mib[6] = {CTL_KERN, KERN_PROC2, 0, 0, sizeof(struct kinfo_proc2), 0}; |
int smib[2] = {CTL_KERN, KERN_NPROCS}; |
|
static int maxslp_mib[] = {CTL_VM, VM_MAXSLP}; |
static int maxslp_mib[] = {CTL_VM, VM_MAXSLP}; |
static struct kinfo_proc *procbase; |
static struct kinfo_proc2 *procbase; |
int st; |
int st; |
|
|
mib[2] = op; |
mib[2] = op; |
|
|
warn("sysctl vm.maxslp failed"); |
warn("sysctl vm.maxslp failed"); |
return (0); |
return (0); |
} |
} |
st = sysctl(smib, 2, cnt, &size, NULL, 0); |
retry: |
|
free(procbase); |
|
st = sysctl(mib, 6, NULL, &size, NULL, 0); |
if (st == -1) { |
if (st == -1) { |
/* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */ |
/* _kvm_syserr(kd, kd->program, "kvm_getproc2"); */ |
return (0); |
return (0); |
} |
} |
if (procbase) |
size = 5 * size / 4; /* extra slop */ |
free(procbase); |
if ((procbase = malloc(size)) == NULL) |
size = (6 * (*cnt) * sizeof(struct kinfo_proc)) / 5; |
|
procbase = (struct kinfo_proc *) malloc(size); |
|
if (procbase == NULL) |
|
return (0); |
return (0); |
st = sysctl(mib, 4, procbase, &size, NULL, 0); |
mib[5] = (int)(size / sizeof(struct kinfo_proc2)); |
|
st = sysctl(mib, 6, procbase, &size, NULL, 0); |
if (st == -1) { |
if (st == -1) { |
/* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */ |
if (errno == ENOMEM) |
|
goto retry; |
|
/* _kvm_syserr(kd, kd->program, "kvm_getproc2"); */ |
return (0); |
return (0); |
} |
} |
if (size % sizeof(struct kinfo_proc) != 0) { |
*cnt = (int)(size / sizeof(struct kinfo_proc2)); |
/* |
|
* _kvm_err(kd, kd->program, "proc size mismatch (%d total, |
|
* %d chunks)", size, sizeof(struct kinfo_proc)); |
|
*/ |
|
return (0); |
|
} |
|
return (procbase); |
return (procbase); |
} |
} |
|
|
|
|
{ |
{ |
int show_idle, show_system, show_uid; |
int show_idle, show_system, show_uid; |
int total_procs, active_procs, i; |
int total_procs, active_procs, i; |
struct kinfo_proc **prefp, *pp; |
struct kinfo_proc2 **prefp, *pp; |
|
|
if ((pbase = getprocs(KERN_PROC_KTHREAD, 0, &nproc)) == NULL) { |
if ((pbase = getprocs(KERN_PROC_KTHREAD, 0, &nproc)) == NULL) { |
/* warnx("%s", kvm_geterr(kd)); */ |
/* warnx("%s", kvm_geterr(kd)); */ |
quit(23); |
quit(23); |
} |
} |
if (nproc > onproc) |
if (nproc > onproc) |
pref = (struct kinfo_proc **)realloc(pref, |
pref = (struct kinfo_proc2 **)realloc(pref, |
sizeof(struct kinfo_proc *) * (onproc = nproc)); |
sizeof(struct kinfo_proc2 *) * (onproc = nproc)); |
if (pref == NULL) { |
if (pref == NULL) { |
warnx("Out of memory."); |
warnx("Out of memory."); |
quit(23); |
quit(23); |
|
|
* status field. Processes with SSYS set are system |
* status field. Processes with SSYS set are system |
* processes---these get ignored unless show_sysprocs is set. |
* processes---these get ignored unless show_sysprocs is set. |
*/ |
*/ |
if (PP(pp, p_stat) != 0 && |
if (pp->p_stat != 0 && |
(show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0))) { |
(show_system || (pp->p_flag & P_SYSTEM) == 0)) { |
total_procs++; |
total_procs++; |
process_states[(unsigned char) PP(pp, p_stat)]++; |
process_states[(unsigned char) pp->p_stat]++; |
if ((PP(pp, p_stat) != SZOMB) && |
if (pp->p_stat != SZOMB && |
(show_idle || (PP(pp, p_pctcpu) != 0) || |
(show_idle || pp->p_pctcpu != 0 || |
(PP(pp, p_stat) == SRUN)) && |
pp->p_stat == SRUN) && |
(!show_uid || EP(pp, e_pcred.p_ruid) == sel->uid)) { |
(!show_uid || pp->p_ruid == sel->uid)) { |
*prefp++ = pp; |
*prefp++ = pp; |
active_procs++; |
active_procs++; |
} |
} |
|
|
/* if requested, sort the "interesting" processes */ |
/* if requested, sort the "interesting" processes */ |
if (compare != NULL) |
if (compare != NULL) |
qsort((char *) pref, active_procs, |
qsort((char *) pref, active_procs, |
sizeof(struct kinfo_proc *), compare); |
sizeof(struct kinfo_proc2 *), compare); |
/* remember active and total counts */ |
/* remember active and total counts */ |
si->p_total = total_procs; |
si->p_total = total_procs; |
si->p_active = pref_len = active_procs; |
si->p_active = pref_len = active_procs; |
|
|
format_next_process(caddr_t handle, char *(*get_userid)(uid_t)) |
format_next_process(caddr_t handle, char *(*get_userid)(uid_t)) |
{ |
{ |
char *p_wait, waddr[sizeof(void *) * 2 + 3]; /* Hexify void pointer */ |
char *p_wait, waddr[sizeof(void *) * 2 + 3]; /* Hexify void pointer */ |
struct kinfo_proc *pp; |
struct kinfo_proc2 *pp; |
struct handle *hp; |
struct handle *hp; |
int cputime; |
int cputime; |
double pct; |
double pct; |
|
|
pp = *(hp->next_proc++); |
pp = *(hp->next_proc++); |
hp->remaining--; |
hp->remaining--; |
|
|
/* get the process's user struct and set cputime */ |
if ((pp->p_flag & P_INMEM) == 0) { |
if ((PP(pp, p_flag) & P_INMEM) == 0) { |
|
/* |
/* |
* Print swapped processes as <pname> |
* Print swapped processes as <pname> |
*/ |
*/ |
char *comm = PP(pp, p_comm); |
char buf[sizeof(pp->p_comm)]; |
char buf[sizeof(PP(pp, p_comm))]; |
|
|
|
(void) strlcpy(buf, comm, sizeof buf); |
(void) strlcpy(buf, pp->p_comm, sizeof(buf)); |
comm[0] = '<'; |
(void) snprintf(pp->p_comm, sizeof(pp->p_comm), "<%s>", buf); |
(void) strlcpy(&comm[1], buf, sizeof buf - 1); |
|
(void) strlcat(comm, ">", sizeof buf); |
|
} |
} |
cputime = (PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks)) / stathz; |
cputime = (pp->p_uticks + pp->p_sticks + pp->p_iticks) / stathz; |
|
|
/* calculate the base for cpu percentages */ |
/* calculate the base for cpu percentages */ |
pct = pctdouble(PP(pp, p_pctcpu)); |
pct = pctdouble(pp->p_pctcpu); |
|
|
if (PP(pp, p_wchan)) { |
if (pp->p_wchan) { |
if (PP(pp, p_wmesg)) |
if (pp->p_wmesg) |
p_wait = EP(pp, e_wmesg); |
p_wait = pp->p_wmesg; |
else { |
else { |
snprintf(waddr, sizeof(waddr), "%lx", |
snprintf(waddr, sizeof(waddr), "%llx", |
(unsigned long) (PP(pp, p_wchan)) & ~KERNBASE); |
pp->p_wchan & ~KERNBASE); |
p_wait = waddr; |
p_wait = waddr; |
} |
} |
} else |
} else |
|
|
|
|
/* format this entry */ |
/* format this entry */ |
snprintf(fmt, sizeof fmt, Proc_format, |
snprintf(fmt, sizeof fmt, Proc_format, |
PP(pp, p_pid), (*get_userid) (EP(pp, e_pcred.p_ruid)), |
pp->p_pid, (*get_userid)(pp->p_ruid), |
PP(pp, p_priority) - PZERO, PP(pp, p_nice) - NZERO, |
pp->p_priority - PZERO, pp->p_nice - NZERO, |
format_k(pagetok(PROCSIZE(pp))), |
format_k(pagetok(PROCSIZE(pp))), |
format_k(pagetok(VP(pp, vm_rssize))), |
format_k(pagetok(pp->p_vm_rssize)), |
(PP(pp, p_stat) == SSLEEP && PP(pp, p_slptime) > maxslp) ? |
(pp->p_stat == SSLEEP && pp->p_slptime > maxslp) ? |
"idle" : state_abbrev[(unsigned char) PP(pp, p_stat)], |
"idle" : state_abbrev[(unsigned char)pp->p_stat], |
p_wait, format_time(cputime), 100.0 * pct, |
p_wait, format_time(cputime), 100.0 * pct, |
printable(PP(pp, p_comm))); |
printable(pp->p_comm)); |
|
|
/* return the result */ |
/* return the result */ |
return (fmt); |
return (fmt); |
|
|
*/ |
*/ |
|
|
#define ORDERKEY_PCTCPU \ |
#define ORDERKEY_PCTCPU \ |
if (lresult = (pctcpu)PP(p2, p_pctcpu) - (pctcpu)PP(p1, p_pctcpu), \ |
if (lresult = (pctcpu)p2->p_pctcpu - (pctcpu)p1->p_pctcpu, \ |
(result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0) |
(result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0) |
#define ORDERKEY_CPUTIME \ |
#define ORDERKEY_CPUTIME \ |
if ((result = PP(p2, p_rtime.tv_sec) - PP(p1, p_rtime.tv_sec)) == 0) \ |
if ((result = p2->p_rtime_sec - p1->p_rtime_sec) == 0) \ |
if ((result = PP(p2, p_rtime.tv_usec) - \ |
if ((result = p2->p_rtime_usec - p1->p_rtime_usec) == 0) |
PP(p1, p_rtime.tv_usec)) == 0) |
|
#define ORDERKEY_STATE \ |
#define ORDERKEY_STATE \ |
if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - \ |
if ((result = sorted_state[(unsigned char)p2->p_stat] - \ |
sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) |
sorted_state[(unsigned char)p1->p_stat]) == 0) |
#define ORDERKEY_PRIO \ |
#define ORDERKEY_PRIO \ |
if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0) |
if ((result = p2->p_priority - p1->p_priority) == 0) |
#define ORDERKEY_RSSIZE \ |
#define ORDERKEY_RSSIZE \ |
if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0) |
if ((result = p2->p_vm_rssize - p1->p_vm_rssize) == 0) |
#define ORDERKEY_MEM \ |
#define ORDERKEY_MEM \ |
if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0) |
if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0) |
|
|
|
|
{ |
{ |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp2 = (struct proc **) v2; |
struct proc **pp2 = (struct proc **) v2; |
struct kinfo_proc *p1, *p2; |
struct kinfo_proc2 *p1, *p2; |
pctcpu lresult; |
pctcpu lresult; |
int result; |
int result; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc2 **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc2 **) pp2; |
|
|
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
ORDERKEY_CPUTIME |
ORDERKEY_CPUTIME |
|
|
{ |
{ |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp2 = (struct proc **) v2; |
struct proc **pp2 = (struct proc **) v2; |
struct kinfo_proc *p1, *p2; |
struct kinfo_proc2 *p1, *p2; |
pctcpu lresult; |
pctcpu lresult; |
int result; |
int result; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc2 **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc2 **) pp2; |
|
|
ORDERKEY_MEM |
ORDERKEY_MEM |
ORDERKEY_RSSIZE |
ORDERKEY_RSSIZE |
|
|
{ |
{ |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp2 = (struct proc **) v2; |
struct proc **pp2 = (struct proc **) v2; |
struct kinfo_proc *p1, *p2; |
struct kinfo_proc2 *p1, *p2; |
pctcpu lresult; |
pctcpu lresult; |
int result; |
int result; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc2 **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc2 **) pp2; |
|
|
ORDERKEY_RSSIZE |
ORDERKEY_RSSIZE |
ORDERKEY_MEM |
ORDERKEY_MEM |
|
|
{ |
{ |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp2 = (struct proc **) v2; |
struct proc **pp2 = (struct proc **) v2; |
struct kinfo_proc *p1, *p2; |
struct kinfo_proc2 *p1, *p2; |
pctcpu lresult; |
pctcpu lresult; |
int result; |
int result; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc2 **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc2 **) pp2; |
|
|
ORDERKEY_CPUTIME |
ORDERKEY_CPUTIME |
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
|
|
{ |
{ |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp1 = (struct proc **) v1; |
struct proc **pp2 = (struct proc **) v2; |
struct proc **pp2 = (struct proc **) v2; |
struct kinfo_proc *p1, *p2; |
struct kinfo_proc2 *p1, *p2; |
pctcpu lresult; |
pctcpu lresult; |
int result; |
int result; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc2 **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc2 **) pp2; |
|
|
ORDERKEY_PRIO |
ORDERKEY_PRIO |
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
|
|
uid_t |
uid_t |
proc_owner(pid_t pid) |
proc_owner(pid_t pid) |
{ |
{ |
struct kinfo_proc **prefp, *pp; |
struct kinfo_proc2 **prefp, *pp; |
int cnt; |
int cnt; |
|
|
prefp = pref; |
prefp = pref; |
cnt = pref_len; |
cnt = pref_len; |
while (--cnt >= 0) { |
while (--cnt >= 0) { |
pp = *prefp++; |
pp = *prefp++; |
if (PP(pp, p_pid) == pid) |
if (pp->p_pid == pid) |
return ((uid_t) EP(pp, e_pcred.p_ruid)); |
return ((uid_t)pp->p_ruid); |
} |
} |
return (uid_t)(-1); |
return (uid_t)(-1); |
} |
} |