Add procstat(1), a process inspection utility. This provides both some
of the missing functionality from procfs(4) and new functionality for monitoring and debugging specific processes. procstat(1) operates in the following modes: -b Display binary information for the process. -c Display command line arguments for the process. -f Display file descriptor information for the process. -k Display the stacks of kernel threads in the process. -s Display security credential information for the process. -t Display thread information for the process. -v Display virtual memory mappings for the process. Further revision and modes are expected. Testing, ideas, etc: cognet, sam, Skip Ford <skip at menantico dot com> Wesley Shields <wxs at atarininja dot org>
This commit is contained in:
parent
02b0457cc2
commit
3d91be41d1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=174199
15
usr.bin/procstat/Makefile
Normal file
15
usr.bin/procstat/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= procstat
|
||||
MAN= procstat.1
|
||||
SRCS= procstat.c \
|
||||
procstat_args.c \
|
||||
procstat_basic.c \
|
||||
procstat_bin.c \
|
||||
procstat_cred.c \
|
||||
procstat_files.c \
|
||||
procstat_kstack.c \
|
||||
procstat_threads.c \
|
||||
procstat_vm.c
|
||||
|
||||
.include <bsd.prog.mk>
|
114
usr.bin/procstat/procstat.1
Normal file
114
usr.bin/procstat/procstat.1
Normal file
@ -0,0 +1,114 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 2007 Robert N. M. Watson
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 30, 2007
|
||||
.Dt PROCSTAT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm procstat
|
||||
.Nd get detailed process information
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl h
|
||||
.Op Fl w Ar interval
|
||||
.Op Fl b | c | f | k | s | t | v
|
||||
.Op Fl a | Ar pid ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility displays detailed information about the processes identified by the
|
||||
.Ar pid
|
||||
arguments, or if the
|
||||
.Fl a
|
||||
flag is used, all processes.
|
||||
.Pp
|
||||
By default, basic process statistics are printed; one of the following
|
||||
options may be specified in order to select more detailed process information
|
||||
for printing:
|
||||
.Bl -tag -width indent
|
||||
.It Fl b
|
||||
Display binary information for the process.
|
||||
.It Fl c
|
||||
Display command line arguments for the process.
|
||||
.It Fl f
|
||||
Display file descriptor information for the process.
|
||||
.It Fl k
|
||||
Display the stacks of kernel threads in the process, excluding stacks of
|
||||
threads currently running on a CPU and threads with stacks swapped to disk.
|
||||
If the flag is repeated, function offsets as well as function names are
|
||||
printed.
|
||||
This feature requires
|
||||
.Cd "options STACK"
|
||||
or
|
||||
.Cd "options DDB"
|
||||
to be compiled into the kernel.
|
||||
.It Fl s
|
||||
Display security credential information for the process.
|
||||
.It Fl t
|
||||
Display thread information for the process.
|
||||
.It Fl v
|
||||
Display virtual memory mappings for the process.
|
||||
.El
|
||||
.Pp
|
||||
All options generate output in the format of a table, the first field of
|
||||
which is the process ID to which the row of information corresponds.
|
||||
The
|
||||
.Fl h
|
||||
flag may be used to suppress table headers.
|
||||
.Pp
|
||||
The
|
||||
.Fl w
|
||||
flag may be used to specify a wait interval at which to repeat the printing
|
||||
of the requested process information.
|
||||
If the
|
||||
.Fl w
|
||||
flag is not specified, the output will not repeat.
|
||||
.Pp
|
||||
Some information, such as VM and file descriptor information, is available
|
||||
only to the owner of a process or the superuser.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr fstat 1 ,
|
||||
.Xr ps 1 ,
|
||||
.Xr sockstat 1 ,
|
||||
.Xr DDB 4 ,
|
||||
.Xr stack 9
|
||||
.Sh AUTHORS
|
||||
.An Robert N M Watson
|
||||
.Sh BUGS
|
||||
Some field values may include spaces, which limits the extent to which the
|
||||
output of
|
||||
.Nm
|
||||
may be mechanically parsed.
|
||||
.Pp
|
||||
The display of open file or memory mapping pathnames is implemented using the
|
||||
kernel's name cache.
|
||||
It therefore does not work for file systems
|
||||
that do not use the name cache, such as
|
||||
.Xr devfs 4 ,
|
||||
or if the name is not present in the cache due to removal.
|
252
usr.bin/procstat/procstat.c
Normal file
252
usr.bin/procstat/procstat.c
Normal file
@ -0,0 +1,252 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
static int aflag, bflag, cflag, fflag, kflag, sflag, tflag, vflag;
|
||||
int hflag;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: procstat [-h] [-w interval] [-b | -c | -f | "
|
||||
"-k | -s | -t | -v]\n");
|
||||
fprintf(stderr, " [-a | pid ...]\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
static void
|
||||
procstat(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
|
||||
if (bflag)
|
||||
procstat_bin(pid, kipp);
|
||||
else if (cflag)
|
||||
procstat_args(pid, kipp);
|
||||
else if (fflag)
|
||||
procstat_files(pid, kipp);
|
||||
else if (kflag)
|
||||
procstat_kstack(pid, kipp, kflag);
|
||||
else if (sflag)
|
||||
procstat_cred(pid, kipp);
|
||||
else if (tflag)
|
||||
procstat_threads(pid, kipp);
|
||||
else if (vflag)
|
||||
procstat_vm(pid, kipp);
|
||||
else
|
||||
procstat_basic(pid, kipp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort processes first by pid and then tid.
|
||||
*/
|
||||
static int
|
||||
kinfo_proc_compare(const void *a, const void *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = ((struct kinfo_proc *)a)->ki_pid -
|
||||
((struct kinfo_proc *)b)->ki_pid;
|
||||
if (i != 0)
|
||||
return (i);
|
||||
i = ((struct kinfo_proc *)a)->ki_tid -
|
||||
((struct kinfo_proc *)b)->ki_tid;
|
||||
return (i);
|
||||
}
|
||||
|
||||
void
|
||||
kinfo_proc_sort(struct kinfo_proc *kipp, int count)
|
||||
{
|
||||
|
||||
qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, i, interval, name[4], tmp;
|
||||
struct kinfo_proc *kipp;
|
||||
size_t len;
|
||||
long l;
|
||||
pid_t pid;
|
||||
char *dummy;
|
||||
|
||||
interval = 0;
|
||||
while ((ch = getopt(argc, argv, "abcfkhstvw:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
aflag++;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
bflag++;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
cflag++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
fflag++;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
kflag++;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
hflag++;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
sflag++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
tflag++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
vflag++;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
l = strtol(optarg, &dummy, 10);
|
||||
if (*dummy != '\0')
|
||||
usage();
|
||||
if (l < 1 || l > INT_MAX)
|
||||
usage();
|
||||
interval = l;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* We require that either 0 or 1 mode flags be set. */
|
||||
tmp = bflag + cflag + fflag + (kflag ? 1 : 0) + sflag + tflag + vflag;
|
||||
if (!(tmp == 0 || tmp == 1))
|
||||
usage();
|
||||
|
||||
/* We allow -k to be specified up to twice, but not more. */
|
||||
if (kflag > 2)
|
||||
usage();
|
||||
|
||||
/* Must specify either the -a flag or a list of pids. */
|
||||
if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
|
||||
usage();
|
||||
|
||||
do {
|
||||
if (aflag) {
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PROC;
|
||||
|
||||
len = 0;
|
||||
if (sysctl(name, 3, NULL, &len, NULL, 0) < 0)
|
||||
err(-1, "sysctl: kern.proc.all");
|
||||
|
||||
kipp = malloc(len);
|
||||
if (kipp == NULL)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 3, kipp, &len, NULL, 0) < 0) {
|
||||
free(kipp);
|
||||
err(-1, "sysctl: kern.proc.all");
|
||||
}
|
||||
if (len % sizeof(*kipp) != 0)
|
||||
err(-1, "kinfo_proc mismatch");
|
||||
if (kipp->ki_structsize != sizeof(*kipp))
|
||||
err(-1, "kinfo_proc structure mismatch");
|
||||
kinfo_proc_sort(kipp, len / sizeof(*kipp));
|
||||
for (i = 0; i < len / sizeof(*kipp); i++) {
|
||||
procstat(kipp[i].ki_pid, &kipp[i]);
|
||||
|
||||
/* Suppress header after first process. */
|
||||
hflag = 1;
|
||||
}
|
||||
free(kipp);
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
l = strtol(argv[i], &dummy, 10);
|
||||
if (*dummy != '\0')
|
||||
usage();
|
||||
if (l < 0)
|
||||
usage();
|
||||
pid = l;
|
||||
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PID;
|
||||
name[3] = pid;
|
||||
|
||||
len = 0;
|
||||
if (sysctl(name, 4, NULL, &len, NULL, 0) < 0)
|
||||
err(-1, "sysctl: kern.proc.pid: %d", pid);
|
||||
|
||||
kipp = malloc(len);
|
||||
if (kipp == NULL)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kipp, &len, NULL, 0) < 0) {
|
||||
free(kipp);
|
||||
err(-1, "sysctl: kern.proc.pid: %d", pid);
|
||||
}
|
||||
if (len != sizeof(*kipp))
|
||||
err(-1, "kinfo_proc mismatch");
|
||||
if (kipp->ki_structsize != sizeof(*kipp))
|
||||
errx(-1, "kinfo_proc structure mismatch");
|
||||
if (kipp->ki_pid != pid)
|
||||
errx(-1, "kinfo_proc pid mismatch");
|
||||
procstat(pid, kipp);
|
||||
free(kipp);
|
||||
|
||||
/* Suppress header after first process. */
|
||||
hflag = 1;
|
||||
}
|
||||
if (interval)
|
||||
sleep(interval);
|
||||
} while (interval);
|
||||
exit(0);
|
||||
}
|
46
usr.bin/procstat/procstat.h
Normal file
46
usr.bin/procstat/procstat.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef PROCSTAT_H
|
||||
#define PROCSTAT_H
|
||||
|
||||
extern int hflag;
|
||||
|
||||
struct kinfo_proc;
|
||||
void kinfo_proc_sort(struct kinfo_proc *kipp, int count);
|
||||
|
||||
void procstat_args(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_basic(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_bin(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_cred(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_files(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag);
|
||||
void procstat_threads(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_vm(pid_t pid, struct kinfo_proc *kipp);
|
||||
|
||||
#endif /* !PROCSTAT_H */
|
74
usr.bin/procstat/procstat_args.c
Normal file
74
usr.bin/procstat/procstat_args.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
static char args[ARG_MAX];
|
||||
|
||||
void
|
||||
procstat_args(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
int error, name[4];
|
||||
size_t len;
|
||||
char *cp;
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %-70s\n", "PID", "ARGS");
|
||||
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_ARGS;
|
||||
name[3] = pid;
|
||||
len = sizeof(args);
|
||||
error = sysctl(name, 4, args, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH) {
|
||||
warn("sysctl: kern.proc.args: %d", pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
return;
|
||||
if (len == 0 || strlen(args) == 0) {
|
||||
strcpy(args, "-");
|
||||
len = strlen(args) + 1;
|
||||
}
|
||||
|
||||
printf("%5d ", pid);
|
||||
for (cp = args; cp < args + len; cp += strlen(cp) + 1)
|
||||
printf("%s%s", cp != args ? " " : "", cp);
|
||||
printf("\n");
|
||||
}
|
64
usr.bin/procstat/procstat_basic.c
Normal file
64
usr.bin/procstat/procstat_basic.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_basic(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s\n",
|
||||
"PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN",
|
||||
"WCHAN", "EMUL", "COMM");
|
||||
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%5d ", kipp->ki_ppid);
|
||||
printf("%5d ", kipp->ki_pgid);
|
||||
printf("%5d ", kipp->ki_sid);
|
||||
printf("%5d ", kipp->ki_tsid);
|
||||
printf("%3d ", kipp->ki_numthreads);
|
||||
printf("%-8s ", strlen(kipp->ki_login) ? kipp->ki_login : "-");
|
||||
if (kipp->ki_kiflag & KI_LOCKBLOCK) {
|
||||
printf("*%-8s ", strlen(kipp->ki_lockname) ?
|
||||
kipp->ki_lockname : "-");
|
||||
} else {
|
||||
printf("%-9s ", strlen(kipp->ki_wmesg) ?
|
||||
kipp->ki_wmesg : "-");
|
||||
}
|
||||
printf("%-13s ", strcmp(kipp->ki_emul, "null") ? kipp->ki_emul : "-");
|
||||
printf("%-12s\n", kipp->ki_comm);
|
||||
}
|
68
usr.bin/procstat/procstat_bin.c
Normal file
68
usr.bin/procstat/procstat_bin.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_bin(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
char pathname[PATH_MAX];
|
||||
int error, name[4];
|
||||
size_t len;
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %-70s\n", "PID", "PATH");
|
||||
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PATHNAME;
|
||||
name[3] = pid;
|
||||
|
||||
len = sizeof(pathname);
|
||||
error = sysctl(name, 4, pathname, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH) {
|
||||
warn("sysctl: kern.proc.pathname: %d", pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
return;
|
||||
if (len == 0 || strlen(pathname) == 0)
|
||||
strcpy(pathname, "-");
|
||||
|
||||
printf("%5d ", pid);
|
||||
printf("%s\n", pathname);
|
||||
}
|
57
usr.bin/procstat/procstat_cred.c
Normal file
57
usr.bin/procstat/procstat_cred.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_cred(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %5s %5s %5s %5s %5s %5s %-20s\n", "PID", "EUID",
|
||||
"RUID", "SVUID", "EGID", "RGID", "SVGID", "GROUPS");
|
||||
|
||||
printf("%5d ", pid);
|
||||
printf("%5d ", kipp->ki_uid);
|
||||
printf("%5d ", kipp->ki_ruid);
|
||||
printf("%5d ", kipp->ki_svuid);
|
||||
printf("%5d ", kipp->ki_groups[0]);
|
||||
printf("%5d ", kipp->ki_rgid);
|
||||
printf("%5d ", kipp->ki_svgid);
|
||||
for (i = 0; i < kipp->ki_ngroups; i++)
|
||||
printf("%s%d", (i > 0) ? "," : "", kipp->ki_groups[i]);
|
||||
printf("\n");
|
||||
}
|
303
usr.bin/procstat/procstat_files.c
Normal file
303
usr.bin/procstat/procstat_files.c
Normal file
@ -0,0 +1,303 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
static const char *
|
||||
protocol_to_string(int domain, int type, int protocol)
|
||||
{
|
||||
|
||||
switch (domain) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
switch (protocol) {
|
||||
case IPPROTO_TCP:
|
||||
return ("TCP");
|
||||
case IPPROTO_UDP:
|
||||
return ("UDP");
|
||||
case IPPROTO_ICMP:
|
||||
return ("ICMP");
|
||||
case IPPROTO_RAW:
|
||||
return ("RAW");
|
||||
case IPPROTO_SCTP:
|
||||
return ("SCTP");
|
||||
default:
|
||||
return ("??");
|
||||
}
|
||||
|
||||
case AF_LOCAL:
|
||||
switch (type) {
|
||||
case SOCK_STREAM:
|
||||
return ("UDSS");
|
||||
case SOCK_DGRAM:
|
||||
return ("UDSD");
|
||||
default:
|
||||
return ("??");
|
||||
}
|
||||
default:
|
||||
return ("??");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
|
||||
{
|
||||
char buffer2[INET6_ADDRSTRLEN];
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_un *sun;
|
||||
|
||||
switch (ss->ss_family) {
|
||||
case AF_LOCAL:
|
||||
sun = (struct sockaddr_un *)ss;
|
||||
if (strlen(sun->sun_path) == 0)
|
||||
strlcpy(buffer, "-", buflen);
|
||||
else
|
||||
strlcpy(buffer, sun->sun_path, buflen);
|
||||
break;
|
||||
|
||||
case AF_INET:
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
snprintf(buffer, buflen, "%s:%d", inet_ntoa(sin->sin_addr),
|
||||
ntohs(sin->sin_port));
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
sin6 = (struct sockaddr_in6 *)ss;
|
||||
if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2,
|
||||
sizeof(buffer2)) != NULL)
|
||||
snprintf(buffer, buflen, "%s.%d", buffer2,
|
||||
ntohs(sin6->sin6_port));
|
||||
else
|
||||
strlcpy(buffer, "-", sizeof(buffer));
|
||||
break;
|
||||
|
||||
default:
|
||||
strlcpy(buffer, "", buflen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_address(struct sockaddr_storage *ss)
|
||||
{
|
||||
char addr[PATH_MAX];
|
||||
|
||||
addr_to_string(ss, addr, sizeof(addr));
|
||||
printf("%-19s", addr);
|
||||
}
|
||||
|
||||
void
|
||||
procstat_files(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
struct kinfo_file *freep, *kif;
|
||||
int error, i, name[4];
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %3s %1s %1s %-8s %3s %7s %-4s %-35s\n", "PID",
|
||||
"FD", "T", "V", "FLAGS", "REF", "OFFSET", "PROT",
|
||||
"NAME");
|
||||
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_FILEDESC;
|
||||
name[3] = pid;
|
||||
|
||||
error = sysctl(name, 4, NULL, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH && errno != EPERM) {
|
||||
warn("sysctl: kern.proc.filedesc: %d", pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
return;
|
||||
|
||||
freep = kif = malloc(len);
|
||||
if (kif == NULL)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kif, &len, NULL, 0) < 0) {
|
||||
warn("sysctl: kern.proc.filedesc %d", pid);
|
||||
free(freep);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < len / sizeof(*kif); i++, kif++) {
|
||||
if (kif->kf_structsize != sizeof(*kif))
|
||||
errx(-1, "kinfo_file mismatch");
|
||||
printf("%5d ", pid);
|
||||
printf("%3d ", kif->kf_fd);
|
||||
switch (kif->kf_type) {
|
||||
case KF_TYPE_VNODE:
|
||||
str = "v";
|
||||
break;
|
||||
|
||||
case KF_TYPE_SOCKET:
|
||||
str = "s";
|
||||
break;
|
||||
|
||||
case KF_TYPE_PIPE:
|
||||
str = "p";
|
||||
break;
|
||||
|
||||
case KF_TYPE_FIFO:
|
||||
str = "f";
|
||||
break;
|
||||
|
||||
case KF_TYPE_KQUEUE:
|
||||
str = "k";
|
||||
break;
|
||||
|
||||
case KF_TYPE_CRYPTO:
|
||||
str = "c";
|
||||
break;
|
||||
|
||||
case KF_TYPE_MQUEUE:
|
||||
str = "m";
|
||||
break;
|
||||
|
||||
case KF_TYPE_NONE:
|
||||
case KF_TYPE_UNKNOWN:
|
||||
default:
|
||||
str = "?";
|
||||
break;
|
||||
}
|
||||
printf("%1s ", str);
|
||||
str = "-";
|
||||
if (kif->kf_type == KF_TYPE_VNODE) {
|
||||
switch (kif->kf_vnode_type) {
|
||||
case KF_VTYPE_VREG:
|
||||
str = "r";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VDIR:
|
||||
str = "d";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VBLK:
|
||||
str = "b";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VCHR:
|
||||
str = "c";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VLNK:
|
||||
str = "l";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VSOCK:
|
||||
str = "s";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VFIFO:
|
||||
str = "f";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VBAD:
|
||||
str = "x";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VNON:
|
||||
case KF_VTYPE_UNKNOWN:
|
||||
default:
|
||||
str = "?";
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("%1s ", str);
|
||||
printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-");
|
||||
printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-");
|
||||
printf("%3d ", kif->kf_ref_count);
|
||||
printf("%7jd ", (intmax_t)kif->kf_offset);
|
||||
|
||||
switch (kif->kf_type) {
|
||||
case KF_TYPE_VNODE:
|
||||
case KF_TYPE_FIFO:
|
||||
printf("%-4s ", "-");
|
||||
printf("%-35s", kif->kf_path);
|
||||
break;
|
||||
|
||||
case KF_TYPE_SOCKET:
|
||||
printf("%-4s ",
|
||||
protocol_to_string(kif->kf_sock_domain,
|
||||
kif->kf_sock_type, kif->kf_sock_protocol));
|
||||
/*
|
||||
* While generally we like to print two addresses,
|
||||
* local and peer, for sockets, it turns out to be
|
||||
* more useful to print the first non-nul address for
|
||||
* local sockets, as typically they aren't bound and
|
||||
* connected, and the path strings can get long.
|
||||
*/
|
||||
if (kif->kf_sock_domain == AF_LOCAL) {
|
||||
struct sockaddr_un *sun =
|
||||
(struct sockaddr_un *)&kif->kf_sa_local;
|
||||
|
||||
if (sun->sun_path[0] != 0)
|
||||
print_address(&kif->kf_sa_local);
|
||||
else
|
||||
print_address(&kif->kf_sa_peer);
|
||||
} else {
|
||||
print_address(&kif->kf_sa_local);
|
||||
printf(" ");
|
||||
print_address(&kif->kf_sa_peer);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%-4s ", "-");
|
||||
printf("%-35s", "-");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
free(freep);
|
||||
}
|
198
usr.bin/procstat/procstat_kstack.c
Normal file
198
usr.bin/procstat/procstat_kstack.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
/*
|
||||
* Walk the stack trace provided by the kernel and reduce it to what we
|
||||
* actually want to print. This involves stripping true instruction pointers,
|
||||
* frame numbers, and carriage returns as generated by stack(9). If -kk is
|
||||
* specified, print the function and offset, otherwise just the function.
|
||||
*/
|
||||
enum trace_state { TS_FRAMENUM, TS_PC, TS_AT, TS_FUNC, TS_OFF };
|
||||
|
||||
static enum trace_state
|
||||
kstack_nextstate(enum trace_state ts)
|
||||
{
|
||||
|
||||
switch (ts) {
|
||||
case TS_FRAMENUM:
|
||||
return (TS_PC);
|
||||
|
||||
case TS_PC:
|
||||
return (TS_AT);
|
||||
|
||||
case TS_AT:
|
||||
return (TS_FUNC);
|
||||
|
||||
case TS_FUNC:
|
||||
return (TS_OFF);
|
||||
|
||||
case TS_OFF:
|
||||
return TS_FRAMENUM;
|
||||
|
||||
default:
|
||||
errx(-1, "kstack_nextstate");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kstack_cleanup(const char *old, char *new, int kflag)
|
||||
{
|
||||
enum trace_state old_ts, ts;
|
||||
const char *cp_old;
|
||||
char *cp_new;
|
||||
|
||||
ts = TS_FRAMENUM;
|
||||
for (cp_old = old, cp_new = new; *cp_old != '\0'; cp_old++) {
|
||||
switch (*cp_old) {
|
||||
case ' ':
|
||||
case '\n':
|
||||
case '+':
|
||||
old_ts = ts;
|
||||
ts = kstack_nextstate(old_ts);
|
||||
if (old_ts == TS_OFF) {
|
||||
*cp_new = ' ';
|
||||
cp_new++;
|
||||
}
|
||||
if (kflag > 1 && old_ts == TS_FUNC) {
|
||||
*cp_new = '+';
|
||||
cp_new++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ts == TS_FUNC || (kflag > 1 && ts == TS_OFF)) {
|
||||
*cp_new = *cp_old;
|
||||
cp_new++;
|
||||
}
|
||||
}
|
||||
*cp_new = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort threads by tid.
|
||||
*/
|
||||
static int
|
||||
kinfo_kstack_compare(const void *a, const void *b)
|
||||
{
|
||||
|
||||
return ((struct kinfo_kstack *)a)->kkst_tid -
|
||||
((struct kinfo_kstack *)b)->kkst_tid;
|
||||
}
|
||||
|
||||
static void
|
||||
kinfo_kstack_sort(struct kinfo_kstack *kkstp, int count)
|
||||
{
|
||||
|
||||
qsort(kkstp, count, sizeof(*kkstp), kinfo_kstack_compare);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag)
|
||||
{
|
||||
struct kinfo_kstack *kkstp, *kkstp_free;
|
||||
char trace[KKST_MAXLEN];
|
||||
int error, i, name[4];
|
||||
size_t len;
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %6s %-20s %-45s\n", "PID", "TID", "COMM",
|
||||
"KSTACK");
|
||||
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_KSTACK;
|
||||
name[3] = pid;
|
||||
|
||||
len = 0;
|
||||
error = sysctl(name, 4, NULL, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) {
|
||||
warn("sysctl: kern.proc.kstack: %d", pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0 && errno == ENOENT)
|
||||
errx(-1, "kern.proc.kstack sysctl unavailable; options DDB "
|
||||
"is required.");
|
||||
if (error < 0)
|
||||
return;
|
||||
|
||||
kkstp = kkstp_free = malloc(len);
|
||||
if (kkstp == NULL)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kkstp, &len, NULL, 0) < 0) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
free(kkstp);
|
||||
return;
|
||||
}
|
||||
|
||||
kinfo_kstack_sort(kkstp, len / sizeof(*kkstp));
|
||||
for (i = 0; i < len / sizeof(*kkstp); i++) {
|
||||
kkstp = &kkstp_free[i];
|
||||
printf("%5d ", pid);
|
||||
printf("%6d ", kkstp->kkst_tid);
|
||||
printf("%-20s ", kipp->ki_comm);
|
||||
|
||||
switch (kkstp->kkst_state) {
|
||||
case KKST_STATE_RUNNING:
|
||||
printf("%-45s\n", "<running>");
|
||||
continue;
|
||||
|
||||
case KKST_STATE_SWAPPED:
|
||||
printf("%-45s\n", "<swapped>");
|
||||
continue;
|
||||
|
||||
case KKST_STATE_STACKOK:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%-45s\n", "<unknown>");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* The kernel generates a trace with carriage returns between
|
||||
* entries, but for a more compact view, we convert carriage
|
||||
* returns to spaces.
|
||||
*/
|
||||
kstack_cleanup(kkstp->kkst_trace, trace, kflag);
|
||||
printf("%-45s\n", trace);
|
||||
}
|
||||
free(kkstp_free);
|
||||
}
|
138
usr.bin/procstat/procstat_threads.c
Normal file
138
usr.bin/procstat/procstat_threads.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_threads(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
struct kinfo_proc *kip;
|
||||
int error, i, name[4];
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %6s %-20s %2s %4s %-7s %-9s\n", "PID", "TID",
|
||||
"COMM", "CPU", "PRI", "STATE", "WCHAN");
|
||||
|
||||
/*
|
||||
* We need to re-query for thread information, so don't use *kipp.
|
||||
*/
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD;
|
||||
name[3] = pid;
|
||||
|
||||
len = 0;
|
||||
error = sysctl(name, 4, NULL, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
return;
|
||||
|
||||
kip = malloc(len);
|
||||
if (kip == NULL)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kip, &len, NULL, 0) < 0) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
free(kip);
|
||||
return;
|
||||
}
|
||||
|
||||
kinfo_proc_sort(kip, len / sizeof(*kipp));
|
||||
for (i = 0; i < len / sizeof(*kipp); i++) {
|
||||
kipp = &kip[i];
|
||||
printf("%5d ", pid);
|
||||
printf("%6d ", kipp->ki_tid);
|
||||
printf("%-20s ", strlen(kipp->ki_comm) ?
|
||||
kipp->ki_comm : "-");
|
||||
if (kipp->ki_oncpu != 255)
|
||||
printf("%3d ", kipp->ki_oncpu);
|
||||
else if (kipp->ki_lastcpu != 255)
|
||||
printf("%3d ", kipp->ki_lastcpu);
|
||||
else
|
||||
printf("%3s ", "-");
|
||||
printf("%4d ", kipp->ki_pri.pri_level);
|
||||
switch (kipp->ki_stat) {
|
||||
case SRUN:
|
||||
str = "run";
|
||||
break;
|
||||
|
||||
case SSTOP:
|
||||
str = "stop";
|
||||
break;
|
||||
|
||||
case SSLEEP:
|
||||
str = "sleep";
|
||||
break;
|
||||
|
||||
case SLOCK:
|
||||
str = "lock";
|
||||
break;
|
||||
|
||||
case SWAIT:
|
||||
str = "wait";
|
||||
break;
|
||||
|
||||
case SZOMB:
|
||||
str = "zomb";
|
||||
break;
|
||||
|
||||
case SIDL:
|
||||
str = "idle";
|
||||
break;
|
||||
|
||||
default:
|
||||
str = "??";
|
||||
break;
|
||||
}
|
||||
printf("%-7s ", str);
|
||||
if (kipp->ki_kiflag & KI_LOCKBLOCK) {
|
||||
printf("*%-8s ", strlen(kipp->ki_lockname) ?
|
||||
kipp->ki_lockname : "-");
|
||||
} else {
|
||||
printf("%-9s ", strlen(kipp->ki_wmesg) ?
|
||||
kipp->ki_wmesg : "-");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
free(kip);
|
||||
}
|
130
usr.bin/procstat/procstat_vm.c
Normal file
130
usr.bin/procstat/procstat_vm.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_vm(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
struct kinfo_vmentry *freep, *kve;
|
||||
int error, i, name[4], ptrwidth;
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
||||
ptrwidth = 2*sizeof(void *) + 2;
|
||||
if (!hflag)
|
||||
printf("%5s %*s %*s %3s %4s %4s %3s %3s %2s %-2s %-s\n",
|
||||
"PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
|
||||
"PRES", "REF", "SHD", "FL", "TP", "PATH");
|
||||
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_VMMAP;
|
||||
name[3] = pid;
|
||||
|
||||
len = 0;
|
||||
error = sysctl(name, 4, NULL, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH && errno != EPERM) {
|
||||
warn("sysctl: kern.proc.vmmap: %d", pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Especially if running procstat -sv, we may need room for more
|
||||
* mappings when printing than were present when we queried, so pad
|
||||
* out the allocation a bit.
|
||||
*/
|
||||
len += sizeof(*kve) * 3;
|
||||
freep = kve = malloc(len);
|
||||
if (kve == NULL)
|
||||
err(-1, "malloc");
|
||||
if (sysctl(name, 4, kve, &len, NULL, 0) < 0) {
|
||||
warn("sysctl: kern.proc.vmmap: %d", pid);
|
||||
free(freep);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < (len / sizeof(*kve)); i++, kve++) {
|
||||
if (kve->kve_structsize != sizeof(*kve))
|
||||
errx(-1, "kinfo_vmentry structure mismatch");
|
||||
printf("%5d ", pid);
|
||||
printf("%*p ", ptrwidth, kve->kve_start);
|
||||
printf("%*p ", ptrwidth, kve->kve_end);
|
||||
printf("%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
|
||||
printf("%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-");
|
||||
printf("%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-");
|
||||
printf("%4d ", kve->kve_resident);
|
||||
printf("%4d ", kve->kve_private_resident);
|
||||
printf("%3d ", kve->kve_ref_count);
|
||||
printf("%3d ", kve->kve_shadow_count);
|
||||
printf("%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-");
|
||||
printf("%-1s ", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" :
|
||||
"-");
|
||||
switch (kve->kve_type) {
|
||||
case KVME_TYPE_NONE:
|
||||
str = "--";
|
||||
break;
|
||||
case KVME_TYPE_DEFAULT:
|
||||
str = "df";
|
||||
break;
|
||||
case KVME_TYPE_VNODE:
|
||||
str = "vn";
|
||||
break;
|
||||
case KVME_TYPE_SWAP:
|
||||
str = "sw";
|
||||
break;
|
||||
case KVME_TYPE_DEVICE:
|
||||
str = "dv";
|
||||
break;
|
||||
case KVME_TYPE_PHYS:
|
||||
str = "ph";
|
||||
break;
|
||||
case KVME_TYPE_DEAD:
|
||||
str = "dd";
|
||||
break;
|
||||
case KVME_TYPE_UNKNOWN:
|
||||
default:
|
||||
str = "??";
|
||||
break;
|
||||
}
|
||||
printf("%-2s ", str);
|
||||
printf("%-s\n", kve->kve_path);
|
||||
}
|
||||
free(freep);
|
||||
}
|
Loading…
Reference in New Issue
Block a user