ps.c
来自「MINIX2.0操作系统源码 MINIX2.0操作系统源码」· C语言 代码 · 共 566 行 · 第 1/2 页
C
566 行
}
/* Open memory devices and get PS info from the kernel */
if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1) err(KMEM_PATH);
if ((memfd = open(MEM_PATH, O_RDONLY)) == -1) err(MEM_PATH);
if (gettynames() == -1) err("Can't get tty names");
if (ioctl(memfd, MIOCGPSINFO, (void *) &psinfo) == -1)
err("can't get PS info from kernel");
nr_tasks = psinfo.nr_tasks;
nr_procs = psinfo.nr_procs;
/* Allocate memory for process tables */
ps_proc = (struct proc *) malloc((nr_tasks + nr_procs) * sizeof(ps_proc[0]));
ps_mproc = (struct mproc *) malloc(nr_procs * sizeof(ps_mproc[0]));
ps_fproc = (struct fproc *) malloc(nr_procs * sizeof(ps_fproc[0]));
if (ps_proc == NULL || ps_mproc == NULL || ps_fproc == NULL)
err("Out of memory");
/* Get kernel process table */
if (addrread(kmemfd, (phys_clicks) 0,
psinfo.proc, (char *) ps_proc,
(nr_tasks + nr_procs) * sizeof(ps_proc[0]))
!= (nr_tasks + nr_procs) * sizeof(ps_proc[0]))
err("Can't get kernel proc table from /dev/kmem");
/* Get mm/fs process tables */
if (addrread(memfd, ps_proc[nr_tasks + MM_PROC_NR].p_map[D].mem_phys,
psinfo.mproc, (char *) ps_mproc,
nr_procs * sizeof(ps_mproc[0]))
!= nr_procs * sizeof(ps_mproc[0]))
err("Can't get mm proc table from /dev/mem");
if (addrread(memfd, ps_proc[nr_tasks + FS_PROC_NR].p_map[D].mem_phys,
psinfo.fproc, (char *) ps_fproc,
nr_procs * sizeof(ps_fproc[0]))
!= nr_procs * sizeof(ps_fproc[0]))
err("Can't get fs proc table from /dev/mem");
/* We need to know where INIT hangs out. */
for (i = FS_PROC_NR; i < nr_procs; i++) {
if (strcmp(ps_proc[nr_tasks + i].p_name, "INIT") == 0) break;
}
init_proc_nr = i;
/* Now loop through process table and handle each entry */
printf("%s", opt_long ? L_HEADER : S_HEADER);
for (i = -nr_tasks; i < nr_procs; i++) {
if (pstat(i, &buf) != -1 &&
(opt_all || buf.ps_euid == uid || buf.ps_ruid == uid) &&
(opt_notty || majdev(buf.ps_dev) == TTY_MAJ))
if (opt_long) printf(L_FORMAT,
buf.ps_flags, buf.ps_state,
buf.ps_euid, buf.ps_pid, buf.ps_ppid,
buf.ps_pgrp,
off_to_k((buf.ps_tsize
+ buf.ps_stack - buf.ps_data
+ buf.ps_ssize)),
(buf.ps_flags & RECEIVING ?
prrecv(&buf) :
""),
tname((Dev_t) buf.ps_dev),
(buf.ps_utime + buf.ps_stime) / HZ / 60,
(buf.ps_utime + buf.ps_stime) / HZ % 60,
i <= init_proc_nr ? taskname(i) :
(buf.ps_args == NULL ? "" :
buf.ps_args));
else
printf(S_FORMAT,
buf.ps_pid, tname((Dev_t) buf.ps_dev),
(buf.ps_utime + buf.ps_stime) / HZ / 60,
(buf.ps_utime + buf.ps_stime) / HZ % 60,
i <= init_proc_nr ? taskname(i) :
(buf.ps_args == NULL ? "" :
buf.ps_args));
}
return(0);
}
char *get_args(bufp)
struct pstat *bufp;
{
int nargv;
int cnt; /* # of bytes read from stack frame */
int neos; /* # of '\0's seen in argv string space */
phys_bytes iframe;
long l;
char *cp, *args;
static union stack {
vir_bytes stk_i;
char *stk_cp;
char stk_c;
} stk[ARG_MAX / sizeof(char *)];
union stack *sp;
/* Phys address of the original stack frame. */
iframe = bufp->ps_procargs - bufp->ps_vstack + bufp->ps_stack;
/* Calculate the number of bytes to read from user stack */
l = (phys_bytes) bufp->ps_ssize - (iframe - bufp->ps_stack);
if (l > ARG_MAX) l = ARG_MAX;
cnt = l;
/* Get cnt bytes from user initial stack to local stack buffer */
if (lseek(memfd, (off_t) iframe, 0) < 0)
return NULL;
if ( read(memfd, (char *)stk, cnt) != cnt )
return NULL;
sp = stk;
nargv = (int) sp[0].stk_i; /* number of argv arguments */
/* See if argv[0] is with the bytes we read in */
l = (long) sp[1].stk_cp - (long) bufp->ps_procargs;
if ( ( l < 0 ) || ( l > cnt ) )
return NULL;
/* l is the offset of the argv[0] argument */
/* change for concatenation the '\0' to space, for nargv elements */
args = &((char *) stk)[(int)l];
neos = 0;
for (cp = args; cp < &((char *) stk)[cnt]; cp++)
if (*cp == '\0')
if (++neos >= nargv)
break;
else
*cp = ' ';
if (cp == args) return NULL;
*cp = '\0';
return args;
}
/* Pstat collects info on process number p_nr and returns it in buf.
* It is assumed that tasks do not have entries in fproc/mproc.
*/
int pstat(p_nr, bufp)
int p_nr;
struct pstat *bufp;
{
int p_ki = p_nr + nr_tasks; /* kernel proc index */
if (p_nr < -nr_tasks || p_nr >= nr_procs) return -1;
if ((ps_proc[p_ki].p_flags & P_SLOT_FREE)
&& !(ps_mproc[p_nr].mp_flags & IN_USE))
return -1;
bufp->ps_flags = ps_proc[p_ki].p_flags;
if (p_nr >= low_user) {
bufp->ps_dev = ps_fproc[p_nr].fp_tty;
bufp->ps_ftask = ps_fproc[p_nr].fp_task;
} else {
bufp->ps_dev = 0;
bufp->ps_ftask = 0;
}
if (p_nr >= low_user) {
bufp->ps_ruid = ps_mproc[p_nr].mp_realuid;
bufp->ps_euid = ps_mproc[p_nr].mp_effuid;
bufp->ps_pid = ps_mproc[p_nr].mp_pid;
bufp->ps_ppid = ps_mproc[ps_mproc[p_nr].mp_parent].mp_pid;
bufp->ps_pgrp = ps_mproc[p_nr].mp_procgrp;
bufp->ps_mflags = ps_mproc[p_nr].mp_flags;
} else {
bufp->ps_pid = bufp->ps_ppid = 0;
bufp->ps_ruid = bufp->ps_euid = 0;
bufp->ps_pgrp = 0;
bufp->ps_mflags = 0;
}
/* State is interpretation of combined kernel/mm flags for non-tasks */
if (p_nr >= low_user) { /* non-tasks */
if (ps_mproc[p_nr].mp_flags & HANGING)
bufp->ps_state = Z_STATE; /* zombie */
else if (ps_mproc[p_nr].mp_flags & STOPPED)
bufp->ps_state = T_STATE; /* stopped (traced) */
else if (ps_proc[p_ki].p_flags == 0)
bufp->ps_state = R_STATE; /* in run-queue */
else if (ps_mproc[p_nr].mp_flags & (WAITING | PAUSED) ||
ps_fproc[p_nr].fp_suspended == SUSPENDED)
bufp->ps_state = S_STATE; /* sleeping */
else
bufp->ps_state = W_STATE; /* a short wait */
} else { /* tasks are simple */
if (ps_proc[p_ki].p_flags == 0)
bufp->ps_state = R_STATE; /* in run-queue */
else
bufp->ps_state = W_STATE; /* other i.e. waiting */
}
bufp->ps_tsize = (size_t) ps_proc[p_ki].p_map[T].mem_len << CLICK_SHIFT;
bufp->ps_dsize = (size_t) ps_proc[p_ki].p_map[D].mem_len << CLICK_SHIFT;
bufp->ps_ssize = (size_t) ps_proc[p_ki].p_map[S].mem_len << CLICK_SHIFT;
bufp->ps_vtext = (off_t) ps_proc[p_ki].p_map[T].mem_vir << CLICK_SHIFT;
bufp->ps_vdata = (off_t) ps_proc[p_ki].p_map[D].mem_vir << CLICK_SHIFT;
bufp->ps_vstack = (off_t) ps_proc[p_ki].p_map[S].mem_vir << CLICK_SHIFT;
bufp->ps_text = (off_t) ps_proc[p_ki].p_map[T].mem_phys << CLICK_SHIFT;
bufp->ps_data = (off_t) ps_proc[p_ki].p_map[D].mem_phys << CLICK_SHIFT;
bufp->ps_stack = (off_t) ps_proc[p_ki].p_map[S].mem_phys << CLICK_SHIFT;
bufp->ps_recv = ps_proc[p_ki].p_getfrom;
bufp->ps_utime = ps_proc[p_ki].user_time;
bufp->ps_stime = ps_proc[p_ki].sys_time;
bufp->ps_procargs = ps_mproc[p_nr].mp_procargs;
if (bufp->ps_state == Z_STATE)
bufp->ps_args = "<defunct>";
else if (p_nr > init_proc_nr)
bufp->ps_args = get_args(bufp);
return 0;
}
/* Addrread reads nbytes from offset addr to click base of fd into buf. */
int addrread(fd, base, addr, buf, nbytes)
int fd;
phys_clicks base;
vir_bytes addr;
char *buf;
int nbytes;
{
if (lseek(fd, ((off_t) base << CLICK_SHIFT) + addr, 0) < 0)
return -1;
return read(fd, buf, nbytes);
}
void usage(pname)
char *pname;
{
fprintf(stderr, "Usage: %s [-][alx]\n", pname);
exit(1);
}
void err(s)
char *s;
{
extern int errno;
if (errno == 0)
fprintf(stderr, "ps: %s\n", s);
else
fprintf(stderr, "ps: %s: %s\n", s, strerror(errno));
exit(2);
}
/* Fill ttyinfo by fstatting character specials in /dev. */
int gettynames()
{
static char dev_path[] = "/dev/";
struct stat statbuf;
static char path[sizeof(dev_path) + NAME_MAX];
int index;
struct ttyent *ttyp;
index = 0;
while ((ttyp = getttyent()) != NULL) {
strcpy(path, dev_path);
strcat(path, ttyp->ty_name);
if (stat(path, &statbuf) == -1 || !S_ISCHR(statbuf.st_mode))
continue;
if (index >= n_ttyinfo) {
n_ttyinfo= (index+16) * 2;
ttyinfo = realloc(ttyinfo, n_ttyinfo * sizeof(ttyinfo[0]));
if (ttyinfo == NULL) err("Out of memory");
}
ttyinfo[index].tty_dev = statbuf.st_rdev;
strcpy(ttyinfo[index].tty_name, ttyp->ty_name);
index++;
}
endttyent();
while (index < n_ttyinfo) ttyinfo[index++].tty_dev= 0;
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?