ps.c
来自「MINIX2.0操作系统源码 MINIX2.0操作系统源码」· C语言 代码 · 共 566 行 · 第 1/2 页
C
566 行
/* ps - print status Author: Peter Valkenburg */
/* Ps.c, Peter Valkenburg (valke@psy.vu.nl), january 1990.
*
* This is a V7 ps(1) look-alike for MINIX >= 1.5.0.
* It does not support the 'k' option (i.e. cannot read memory from core file).
* If you want to compile this for non-IBM PC architectures, the header files
* require that you have your CHIP, MACHINE etc. defined.
* Full syntax:
* ps [-][alx]
* Option `a' gives all processes, `l' for detailed info, `x' includes even
* processes without a terminal.
*
* VERY IMPORTANT NOTE:
* To compile ps, the kernel/, fs/ and mm/ source directories must be in
* ../ relative to the directory where ps is compiled (normally the
* tools source directory).
*
* If you want your ps to be useable by anyone, you can arrange the
* following access permissions (note the protected memory files and set
* *group* id on ps):
* -rwxr-sr-x 1 bin kmem 11916 Jul 4 15:31 /bin/ps
* crw-r----- 1 bin kmem 1, 1 Jan 1 1970 /dev/mem
* crw-r----- 1 bin kmem 1, 2 Jan 1 1970 /dev/kmem
*/
/* Some technical comments on this implementation:
*
* Most fields are similar to V7 ps(1), except for CPU, NICE, PRI which are
* absent, RECV which replaces WCHAN, and PGRP that is an extra.
* The info is obtained from the following fields of proc, mproc and fproc:
* F - kernel status field, p_flags
* S - kernel status field, p_flags; mm status field, mp_flags (R if p_flags
* is 0; Z if mp_flags == HANGING; T if mp_flags == STOPPED; else W).
* UID - mm eff uid field, mp_effuid
* PID - mm pid field, mp_pid
* PPID - mm parent process index field, mp_parent (used as index in proc).
* PGRP - mm process group field, mp_procgrp
* SZ - kernel text size + physical stack address - physical data address
* + stack size
* p_map[T].mem_len + p_map[S].mem_phys - p_map[D].mem_phys
* + p_map[S].mem_len
* RECV - kernel process index field for message receiving, p_getfrom
* If sleeping, mm's mp_flags, or fs's fp_task are used for more info.
* TTY - fs controlling tty device field, fp_tty.
* TIME - kernel user + system times fields, user_time + sys_time
* CMD - system process index (converted to mnemonic name by using the p_name
* field), or user process argument list (obtained by reading the stack
* frame; the resulting address is used to get the argument vector from
* user space and converted into a concatenated argument list).
*/
#include <minix/config.h>
#include <limits.h>
#include <sys/types.h>
#include <minix/const.h>
#include <minix/type.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <minix/com.h>
#include <fcntl.h>
#include <a.out.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <stdio.h>
#include <ttyent.h>
#include "../kernel/const.h"
#include "../kernel/type.h"
#include "../kernel/proc.h"
#undef printf /* kernel's const.h defined this */
#include "../mm/mproc.h"
#include "../fs/fproc.h"
#include "../fs/const.h"
#undef printf /* fs's const.h defined this */
/*----- ps's local stuff below this line ------*/
#define mindev(dev) (((dev)>>MINOR) & 0377) /* yield minor device */
#define majdev(dev) (((dev)>>MAJOR) & 0377) /* yield major device */
#define TTY_MAJ 4 /* major device of console */
/* Structure for tty name info. */
typedef struct {
char tty_name[NAME_MAX + 1]; /* file name in /dev */
dev_t tty_dev; /* major/minor pair */
} ttyinfo_t;
ttyinfo_t *ttyinfo; /* ttyinfo holds actual tty info */
size_t n_ttyinfo; /* Number of tty info slots */
/* Macro to convert memory offsets to rounded kilo-units */
#define off_to_k(off) ((unsigned) (((off) + 512) / 1024))
/* Number of tasks and processes. */
int nr_tasks, nr_procs;
/* Process tables of the kernel, MM, and FS. */
struct proc *ps_proc;
struct mproc *ps_mproc;
struct fproc *ps_fproc;
/* Where is INIT? */
int init_proc_nr;
#define low_user init_proc_nr
#define KMEM_PATH "/dev/kmem" /* opened for kernel proc table */
#define MEM_PATH "/dev/mem" /* opened for mm/fs + user processes */
int kmemfd, memfd; /* file descriptors of [k]mem */
/* Short and long listing formats:
*
* PID TTY TIME CMD
* ppppp tttmmm:ss cccccccccc...
*
* F S UID PID PPID PGRP SZ RECV TTY TIME CMD
* fff s uuu ppppp ppppp ppppp ssss rrrrrrrrrr tttmmm:ss cccccccc...
*/
#define S_HEADER " PID TTY TIME CMD\n"
#define S_FORMAT "%5d %3s%3ld:%02ld %s\n"
#define L_HEADER " F S UID PID PPID PGRP SZ RECV TTY TIME CMD\n"
#define L_FORMAT "%3o %c %3d %5d %5d %5d %4d %10s %3s%3ld:%02ld %s\n"
struct pstat { /* structure filled by pstat() */
dev_t ps_dev; /* major/minor of controlling tty */
uid_t ps_ruid; /* real uid */
uid_t ps_euid; /* effective uid */
pid_t ps_pid; /* process id */
pid_t ps_ppid; /* parent process id */
int ps_pgrp; /* process group id */
int ps_flags; /* kernel flags */
int ps_mflags; /* mm flags */
int ps_ftask; /* (possibly pseudo) fs suspend task */
char ps_state; /* process state */
vir_bytes ps_tsize; /* text size (in bytes) */
vir_bytes ps_dsize; /* data size (in bytes) */
vir_bytes ps_ssize; /* stack size (in bytes) */
phys_bytes ps_vtext; /* virtual text offset */
phys_bytes ps_vdata; /* virtual data offset */
phys_bytes ps_vstack; /* virtual stack offset */
phys_bytes ps_text; /* physical text offset */
phys_bytes ps_data; /* physical data offset */
phys_bytes ps_stack; /* physical stack offset */
int ps_recv; /* process number to receive from */
time_t ps_utime; /* accumulated user time */
time_t ps_stime; /* accumulated system time */
char *ps_args; /* concatenated argument string */
vir_bytes ps_procargs; /* initial stack frame from MM */
};
/* Ps_state field values in pstat struct above */
#define Z_STATE 'Z' /* Zombie */
#define W_STATE 'W' /* Waiting */
#define S_STATE 'S' /* Sleeping */
#define R_STATE 'R' /* Runnable */
#define T_STATE 'T' /* stopped (Trace) */
_PROTOTYPE(char *tname, (Dev_t dev_nr ));
_PROTOTYPE(char *taskname, (int p_nr ));
_PROTOTYPE(char *prrecv, (struct pstat *bufp ));
_PROTOTYPE(void disaster, (int sig ));
_PROTOTYPE(int main, (int argc, char *argv []));
_PROTOTYPE(char *get_args, (struct pstat *bufp ));
_PROTOTYPE(int pstat, (int p_nr, struct pstat *bufp ));
_PROTOTYPE(int addrread, (int fd, phys_clicks base, vir_bytes addr,
char *buf, int nbytes ));
_PROTOTYPE(void usage, (char *pname ));
_PROTOTYPE(void err, (char *s ));
_PROTOTYPE(int gettynames, (void));
/*
* Tname returns mnemonic string for dev_nr. This is "?" for maj/min pairs that
* are not found. It uses the ttyinfo array (prepared by gettynames).
* Tname assumes that the first three letters of the tty's name can be omitted
* and returns the rest (except for the console, which yields "co").
*/
char *tname(dev_nr)
Dev_t dev_nr;
{
int i;
if (majdev(dev_nr) == TTY_MAJ && mindev(dev_nr) == 0) return "co";
for (i = 0; i < n_ttyinfo && ttyinfo[i].tty_name[0] != '\0'; i++)
if (ttyinfo[i].tty_dev == dev_nr)
return ttyinfo[i].tty_name + 3;
return "?";
}
/* Return canonical task name of task p_nr; overwritten on each call (yucch) */
char *taskname(p_nr)
int p_nr;
{
return ps_proc[p_nr + nr_tasks].p_name;
}
/* Prrecv prints the RECV field for process with pstat buffer pointer bufp.
* This is either "ANY", "taskname", or "(blockreason) taskname".
*/
char *prrecv(bufp)
struct pstat *bufp;
{
char *blkstr, *task; /* reason for blocking and task */
static char recvstr[20];
if (bufp->ps_recv == ANY) return "ANY";
task = taskname(bufp->ps_recv);
if (bufp->ps_state != S_STATE) return task;
blkstr = "?";
if (bufp->ps_recv == MM_PROC_NR) {
if (bufp->ps_mflags & PAUSED)
blkstr = "pause";
else if (bufp->ps_mflags & WAITING)
blkstr = "wait";
} else if (bufp->ps_recv == FS_PROC_NR) {
if (-bufp->ps_ftask == XOPEN)
blkstr = "xopen";
else if (-bufp->ps_ftask == XPIPE)
blkstr = "xpipe";
else
blkstr = taskname(-bufp->ps_ftask);
}
(void) sprintf(recvstr, "(%s) %s", blkstr, task);
return recvstr;
}
/* If disaster is called some of the system parameters imported into ps are
* probably wrong. This tends to result in memory faults.
*/
void disaster(sig)
int sig;
{
fprintf(stderr, "Ooops, got signal %d\n", sig);
fprintf(stderr, "Was ps recompiled since the last kernel change?\n");
exit(3);
}
/* Main interprets arguments, gets system addresses, opens [k]mem, reads in
* process tables from kernel/mm/fs and calls pstat() for relevant entries.
*/
int main(argc, argv)
int argc;
char *argv[];
{
int i;
struct pstat buf;
int db_fd;
int uid = getuid(); /* real uid of caller */
char *opt;
int opt_all = FALSE; /* -a */
int opt_long = FALSE; /* -l */
int opt_notty = FALSE; /* -x */
char *ke_path; /* paths of kernel, */
char *mm_path; /* mm, */
char *fs_path; /* and fs used in ps -U */
struct psinfo psinfo;
(void) signal(SIGSEGV, disaster); /* catch a common crash */
/* Parse arguments; a '-' need not be present (V7/BSD compatability) */
for (i = 1; i < argc; i++) {
opt = argv[i];
if (opt[0] == '-') opt++;
while (*opt != 0) switch (*opt++) {
case 'a': opt_all = TRUE; break;
case 'l': opt_long = TRUE; break;
case 'x': opt_notty = TRUE; break;
default: usage(argv[0]);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?