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 + -
显示快捷键?