Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/bin/ps When using the procfs for extracting process informat...
details: https://anonhg.NetBSD.org/src/rev/696a8b396fb5
branches: trunk
changeset: 477213:696a8b396fb5
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Fri Oct 15 19:31:24 1999 +0000
description:
When using the procfs for extracting process information, extract
also process start time, process arguments and session leadership status.
The procfs fallback is also used when kvm_openfiles() completely fails
(e.g. when /dev/mem is not readable).
Solves PR 7772, though the final implementation is different.
diffstat:
bin/ps/extern.h | 5 +-
bin/ps/print.c | 25 ++++++++---
bin/ps/procfs_ops.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++-----
bin/ps/ps.c | 59 ++++++++++++++++++-------
4 files changed, 166 insertions(+), 38 deletions(-)
diffs (truncated from 451 to 300 lines):
diff -r 4633ef5d3bf9 -r 696a8b396fb5 bin/ps/extern.h
--- a/bin/ps/extern.h Fri Oct 15 17:17:07 1999 +0000
+++ b/bin/ps/extern.h Fri Oct 15 19:31:24 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.13 1999/03/26 22:36:02 bgrayson Exp $ */
+/* $NetBSD: extern.h,v 1.14 1999/10/15 19:31:24 jdolecek Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -68,7 +68,8 @@
void pnice __P((KINFO *, VARENT *));
void pri __P((KINFO *, VARENT *));
void printheader __P((void));
-struct kinfo_proc * procfs_getprocs __P((int, int, int*));
+KINFO *getkinfo_procfs __P((int, int, int*));
+char **procfs_getargv __P((const struct kinfo_proc *, int));
void pvar __P((KINFO *, VARENT *));
void rssize __P((KINFO *, VARENT *));
void runame __P((KINFO *, VARENT *));
diff -r 4633ef5d3bf9 -r 696a8b396fb5 bin/ps/print.c
--- a/bin/ps/print.c Fri Oct 15 17:17:07 1999 +0000
+++ b/bin/ps/print.c Fri Oct 15 19:31:24 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: print.c,v 1.44 1999/10/11 09:18:09 mrg Exp $ */
+/* $NetBSD: print.c,v 1.45 1999/10/15 19:31:24 jdolecek Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94";
#else
-__RCSID("$NetBSD: print.c,v 1.44 1999/10/11 09:18:09 mrg Exp $");
+__RCSID("$NetBSD: print.c,v 1.45 1999/10/15 19:31:24 jdolecek Exp $");
#endif
#endif /* not lint */
@@ -68,7 +68,7 @@
#include "ps.h"
extern kvm_t *kd;
-extern int needenv, needcomm, commandonly;
+extern int needenv, needcomm, commandonly, dontuseprocfs;
static char *cmdpart __P((char *));
static void printval __P((char *, VAR *));
@@ -144,6 +144,7 @@
{
VAR *v;
int left;
+ static int use_procfs=0;
char **argv, **p, *name;
v = ve->var;
@@ -156,7 +157,7 @@
left = v->width;
} else
left = -1;
- if (needenv) {
+ if (needenv && kd) {
argv = kvm_getenvv(kd, ki->ki_p, termwidth);
if ((p = argv) != NULL) {
while (*p) {
@@ -169,7 +170,13 @@
if (needcomm) {
name = KI_PROC(ki)->p_comm;
if (!commandonly) {
- argv = kvm_getargv(kd, ki->ki_p, termwidth);
+ argv = NULL;
+ if (kd && !use_procfs)
+ argv = kvm_getargv(kd, ki->ki_p, termwidth);
+ if (argv == NULL && !dontuseprocfs) {
+ argv = procfs_getargv(ki->ki_p, termwidth);
+ use_procfs = 1;
+ }
if ((p = argv) != NULL) {
while (*p) {
fmt_puts(*p, &left);
@@ -182,6 +189,10 @@
fmt_puts(name, &left);
fmt_putc(')', &left);
}
+ if (use_procfs) {
+ free(argv[0]);
+ free(argv);
+ }
} else {
fmt_puts(name, &left);
}
@@ -549,7 +560,7 @@
static int failure;
if (!nlistread)
- failure = donlist();
+ failure = (kd) ? donlist() : 1;
if (failure)
return (0.0);
@@ -588,7 +599,7 @@
int szptudot;
if (!nlistread)
- failure = donlist();
+ failure = (kd) ? donlist() : 1;
if (failure)
return (0.0);
diff -r 4633ef5d3bf9 -r 696a8b396fb5 bin/ps/procfs_ops.c
--- a/bin/ps/procfs_ops.c Fri Oct 15 17:17:07 1999 +0000
+++ b/bin/ps/procfs_ops.c Fri Oct 15 19:31:24 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: procfs_ops.c,v 1.5 1999/05/09 19:23:38 thorpej Exp $ */
+/* $NetBSD: procfs_ops.c,v 1.6 1999/10/15 19:31:25 jdolecek Exp $ */
/*
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -42,6 +42,7 @@
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/resource.h> /* for rusage */
#include <fcntl.h>
#include <dirent.h>
@@ -52,6 +53,8 @@
#include <err.h>
#include <kvm.h>
+#include "ps.h"
+
/* Assume that no process status file will ever be larger than this. */
#define STATUS_SIZE 8192
@@ -70,8 +73,7 @@
}
static int verify_procfs_fd __P((int, const char *));
-static int parsekinfo __P((const char *, struct kinfo_proc *));
-struct kinfo_proc *procfs_getprocs __P((int, int, int *));
+static int parsekinfo __P((const char *, KINFO *));
static int
verify_procfs_fd(fd, path)
@@ -97,15 +99,16 @@
}
static int
-parsekinfo(path, kp)
+parsekinfo(path, ki)
const char *path;
- struct kinfo_proc *kp;
+ KINFO *ki;
{
char fullpath[MAXPATHLEN];
int dirfd, fd, nbytes, devmajor, devminor;
struct timeval usertime, systime, starttime;
char buff[STATUS_SIZE];
char flagstr[256];
+ struct kinfo_proc *kp = ki->ki_p;
/*
* Verify that /proc/<pid> is a procfs file (and that no one has
@@ -131,7 +134,6 @@
* Don't print warning, as the process may have died since our
* scan of the directory entries.
*/
- close(fd);
return -1; /* Process may no longer exist. */
}
@@ -174,6 +176,14 @@
kp->kp_proc.p_rtime.tv_sec = usertime.tv_sec + systime.tv_sec;
kp->kp_proc.p_rtime.tv_usec = usertime.tv_usec + systime.tv_usec;
+ /* if starttime.[u]sec is != -1, it's in-memory process */
+ if (starttime.tv_sec != -1 && starttime.tv_usec != -1) {
+ kp->kp_proc.p_flag |= P_INMEM;
+ ki->ki_u.u_valid = 1;
+ ki->ki_u.u_start.tv_sec = starttime.tv_sec;
+ ki->ki_u.u_start.tv_usec = starttime.tv_usec;
+ }
+
/*
* CPU time isn't shown unless the ki_u.u_valid flag is set.
* Unfortunately, we don't have access to that here.
@@ -183,11 +193,15 @@
if (strstr(flagstr, "ctty"))
kp->kp_proc.p_flag |= P_CONTROLT;
+ /* Set the flag for whether or not this process is session leader */
+ if (strstr(flagstr, "sldr"))
+ kp->kp_eproc.e_flag |= EPROC_SLEADER;
+
return 0;
}
-struct kinfo_proc *
-procfs_getprocs(op, arg, cnt)
+KINFO *
+getkinfo_procfs(op, arg, cnt)
int op, arg;
int *cnt;
{
@@ -195,6 +209,7 @@
int procdirfd, nbytes, knum = 0, maxknum = 0;
char *direntbuff;
struct kinfo_proc *kp;
+ KINFO *ki;
int mib[4];
size_t len;
struct statfs procfsstat;
@@ -250,8 +265,8 @@
err(1, "sysctl to fetch maxproc");
maxknum *= 2; /* Double it, to be really paranoid. */
- kp = (struct kinfo_proc *) malloc(sizeof(struct kinfo_proc) * maxknum);
- memset(kp, 0, sizeof(struct kinfo_proc) * maxknum);
+ kp = (struct kinfo_proc *) calloc(sizeof(struct kinfo_proc)*maxknum, 1);
+ ki = (KINFO *) calloc(sizeof(KINFO)*maxknum, 1);
/* Read in a batch of entries at a time. */
while ((knum < maxknum) &&
@@ -268,7 +283,8 @@
continue;
if (strcmp(dp->d_name, "curproc") == 0)
continue;
- if (parsekinfo(dp->d_name, &kp[knum]) != 0)
+ ki[knum].ki_p = &kp[knum];
+ if (parsekinfo(dp->d_name, &ki[knum]) != 0)
continue;
/*
* Now check some of the flags. If the newest entry
@@ -323,5 +339,80 @@
*cnt = knum;
close(procdirfd);
- return kp;
+ /* free unused memory */
+ if (knum < maxknum) {
+ kp = realloc(kp, sizeof(*kp) * knum);
+ ki = realloc(ki, sizeof(*ki) * knum);
+ for(; knum >= 0; knum--)
+ ki[knum].ki_p = &kp[knum];
+ }
+ return ki;
}
+
+/*
+ * return process arguments, possibly ones used when exec()ing
+ * the process; return the array as two element array, first is
+ * argv[0], second element is all the other args separated by spaces
+ */
+char **
+procfs_getargv(kp, nchr)
+ const struct kinfo_proc *kp;
+ int nchr;
+{
+ char fullpath[MAXPATHLEN], *buf, *name, *args, **argv;
+ int fd, num;
+ ssize_t len;
+ size_t idx;
+
+ /* Open /proc/<pid>/cmdline, and parse it into the argv array */
+ snprintf(fullpath, MAXPATHLEN, "/proc/%d/cmdline", kp->kp_proc.p_pid);
+ fd = open(fullpath, O_RDONLY, 0);
+ if (fd == -1 || verify_procfs_fd(fd, fullpath)) {
+ /*
+ * Don't print warning, as the process may have died since our
+ * scan of the directory entries.
+ */
+ return NULL; /* Process may no longer exist. */
+ }
+
+ buf = (char *)malloc(nchr+1);
+ len = read(fd, buf, nchr);
+ close(fd);
+ if (len == -1) {
+ warnx("procfs_getargv");
+ return NULL;
+ }
+
+ num = 1;
+ args = NULL;
+ name = buf;
+ /* substitute any \0's with space */
+ for(idx=0; idx < len; idx++) {
+ if (buf[idx] == '\0') {
+ if (!args)
+ args = &buf[idx+1];
+ else
+ buf[idx] = ' ';
+ num++;
+ }
+ }
+ buf[len] = '\0'; /* end the string */
+
+ /* if the name is the same as the p_comm, just enclosed
+ * in parentheses, remove the parentheses */
+ if (num == 1 && name[0] == '(' && name[len-1] == ')'
+ && strncmp(name+1, kp->kp_proc.p_comm, len-2) == 0)
Home |
Main Index |
Thread Index |
Old Index