Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159858591
D29754.id87399.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D29754.id87399.diff
View Options
diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile
--- a/usr.bin/systat/Makefile
+++ b/usr.bin/systat/Makefile
@@ -5,7 +5,7 @@
PROG= systat
SRCS= cmds.c cmdtab.c devs.c fetch.c iostat.c keyboard.c main.c sysput.c \
- netcmds.c netstat.c pigs.c swap.c icmp.c \
+ netcmds.c netstat.c pigs.c proc.c swap.c icmp.c \
mode.c ip.c sctp.c tcp.c zarc.c \
vmstat.c convtbl.c ifcmds.c ifstat.c
@@ -16,6 +16,6 @@
WARNS?= 1
-LIBADD= ncursesw m devstat kvm util
+LIBADD= ncursesw m devstat kvm util procstat
.include <bsd.prog.mk>
diff --git a/usr.bin/systat/devs.h b/usr.bin/systat/devs.h
--- a/usr.bin/systat/devs.h
+++ b/usr.bin/systat/devs.h
@@ -34,6 +34,8 @@
#include <devstat.h>
+#define DISKHIGHT 5
+
int dsinit(int);
void dsgetinfo(struct statinfo *);
int dscmd(const char *, const char *, int, struct statinfo *);
diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c
--- a/usr.bin/systat/main.c
+++ b/usr.bin/systat/main.c
@@ -135,6 +135,21 @@
}
+static void
+resize(int signo __unused)
+{
+
+ endwin();
+ refresh();
+ clear();
+
+ CMDLINE = LINES - 1;
+ labels();
+ display();
+ status();
+}
+
+
int
main(int argc, char **argv)
{
@@ -191,6 +206,7 @@
signal(SIGINT, die);
signal(SIGQUIT, die);
signal(SIGTERM, die);
+ signal(SIGWINCH, resize);
/*
* Initialize display. Load average appears in a one line
diff --git a/usr.bin/systat/proc.c b/usr.bin/systat/proc.c
new file mode 100644
--- /dev/null
+++ b/usr.bin/systat/proc.c
@@ -0,0 +1,192 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Yoshihiro Ota
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <libprocstat.h>
+
+#include <curses.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "subs.h"
+#include "systat.h"
+#include "extern.h"
+
+static int compar(const void *, const void *);
+
+static unsigned int nproc;
+
+static struct procstat *prstat = NULL;
+static struct proc_usage {
+ pid_t pid;
+ uid_t uid;
+ char command[COMMLEN+1];
+ uint64_t total;
+ uint64_t swap;
+} *pu = NULL, pzero;
+
+
+void
+closeproc(WINDOW *w)
+{
+ procstat_close(prstat);
+ prstat = NULL;
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+procshow(int col, int hight, uint64_t totalswappages)
+{
+ int i, j, y, offset;
+ int rate;
+ const char *uname, *pname;
+ char buf[30];
+
+ if (nproc > 1)
+ qsort(pu, nproc, sizeof (struct proc_usage), compar);
+ y = col + 1 /* HEADING */;
+ offset = 0;
+ for (i = 0; i < hight; i++, y++) {
+ wmove(wnd, y, 0);
+ wclrtoeol(wnd);
+ if (i >= nproc)
+ continue;
+
+ uname = user_from_uid(pu[i].uid, 0);
+ snprintf(buf, sizeof(buf), "%6d %-10s %-10.10s", pu[i].pid,
+ uname, pu[i].command);
+ offset = 6 + 1 + 10 + 1 + 10 + 1;
+ mvwaddstr(wnd, y, 0, buf);
+ sysputuint64(wnd, y, offset, 4, pu[i].swap, 0);
+ offset += 4;
+ mvwaddstr(wnd, y, offset, " / ");
+ offset += 3;
+ sysputuint64(wnd, y, offset, 4, pu[i].total, 0);
+ offset += 4;
+
+ rate = (pu[i].total > 1 ? 100 * pu[i].swap / pu[i].total : 0);
+ snprintf(buf, sizeof(buf), "%3d%%", rate);
+ mvwaddstr(wnd, y, offset, buf);
+ sysputXs(wnd, y, offset + 5, rate / 10);
+
+ rate = 100 * byte_to_page(pu[i].swap) / totalswappages;
+ snprintf(buf, sizeof(buf), "%3d%%", rate);
+ mvwaddstr(wnd, y, offset + 16, buf);
+ sysputXs(wnd, y, offset + 21, rate / 10);
+ }
+}
+
+int
+procinit(void)
+{
+
+ if (prstat != NULL)
+ return(1);
+ prstat = procstat_open_sysctl();
+ return (prstat == NULL);
+}
+
+void
+procgetinfo(void)
+{
+ static unsigned int maxnproc = 0;
+ int i, j, k;
+ unsigned int cnt;
+ struct kinfo_proc *kipp;
+ struct kinfo_vmentry *freep, *kve;
+
+ kipp = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &nproc);
+ if (kipp == NULL) {
+ error("procstat_getprocs()");
+ return;
+ }
+
+ if (nproc > maxnproc) {
+ maxnproc = nproc;
+ if ((pu = realloc(pu, maxnproc * sizeof(*pu))) == NULL) {
+ error("Out of memory");
+ die(0);
+ }
+ }
+ for (i = 0, k = 0; i < nproc; i++) {
+ freep = procstat_getvmmap(prstat, &kipp[i], &cnt);
+ if (freep == NULL) {
+ continue;
+ }
+ pu[k].swap = 0;
+ for (j = 0; j < cnt; j++) {
+ kve = &freep[j];
+ if (kve->kve_type == KVME_TYPE_SWAP) {
+ pu[k].swap += kve->kve_end - kve->kve_start;
+ pu[k].swap -= page_to_byte(kve->kve_resident);
+ }
+ }
+ if (pu[k].swap != 0) {
+ strcpy(pu[k].command, kipp[i].ki_comm);
+ pu[k].pid = kipp[i].ki_pid;
+ pu[k].uid = kipp[i].ki_uid;
+ pu[k].total = kipp[i].ki_size;
+ k++;
+ }
+ free(freep);
+ }
+ procstat_freeprocs(prstat, kipp);
+ nproc = k;
+}
+
+void
+proclabel(int col)
+{
+
+ wmove(wnd, col, 0);
+ wclrtoeol(wnd);
+ mvwaddstr(wnd, col, 0,
+ "Pid Username Command Swap/Total "
+ "Per-Process Per-System");
+}
+
+int
+compar(const void *a, const void *b)
+{
+
+ return (((const struct proc_usage *) a)->swap >
+ ((const struct proc_usage *) b)->swap) ? -1: 1;
+}
diff --git a/usr.bin/systat/subs.h b/usr.bin/systat/subs.h
new file mode 100644
--- /dev/null
+++ b/usr.bin/systat/subs.h
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Yoshihiro Ota
+ * 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 SUBS_H
+#define SUBS_H
+
+#include <sys/stdint.h>
+
+int procinit(void);
+void procgetinfo(void);
+
+void proclabel(int col);
+void procshow(int col, int hight, uint64_t totalswappages);
+
+#endif
diff --git a/usr.bin/systat/swap.c b/usr.bin/systat/swap.c
--- a/usr.bin/systat/swap.c
+++ b/usr.bin/systat/swap.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 1980, 1992, 1993
* The Regents of the University of California. All rights reserved.
- * Copyright (c) 2017, 2020 Yoshihiro Ota
+ * Copyright (c) 2017, 2020, 2021 Yoshihiro Ota
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -57,6 +57,7 @@
#include "systat.h"
#include "extern.h"
#include "devs.h"
+#include "subs.h"
static int pathlen;
@@ -103,6 +104,7 @@
}
pathlen = 80 - 50 /* % */ - 5 /* Used */ - 5 /* Size */ - 3 /* space */;
dsinit(12);
+ procinit();
once = 1;
return (1);
@@ -125,18 +127,17 @@
cur_dev.dinfo = tmp_dinfo;
last_dev.snap_time = cur_dev.snap_time;
- dsgetinfo( &cur_dev );
+ dsgetinfo(&cur_dev);
+ procgetinfo();
}
void
labelswap(void)
{
- const char *name;
- int i;
werase(wnd);
- dslabel(12, 0, 18);
+ dslabel(12, 0, LINES - DISKHIGHT - 1);
if (kvnsw <= 0) {
mvwprintw(wnd, 0, 0, "(swap not configured)");
@@ -146,28 +147,26 @@
mvwprintw(wnd, 0, 0, "%*s%5s %5s %s",
-pathlen, "Device/Path", "Size", "Used",
"|0% /10 /20 /30 /40 / 60\\ 70\\ 80\\ 90\\ 100|");
-
- for (i = 0; i <= kvnsw; ++i) {
- name = i == kvnsw ? "Total" : kvmsw[i].ksw_devname;
- mvwprintw(wnd, 1 + i, 0, "%-*.*s", pathlen, pathlen - 1, name);
- }
}
void
showswap(void)
{
- int count;
- int i;
+ const char *name;
+ int count, i;
if (kvnsw != okvnsw)
labelswap();
- dsshow(12, 0, 18, &cur_dev, &last_dev);
+ dsshow(12, 0, LINES - DISKHIGHT - 1, &cur_dev, &last_dev);
if (kvnsw <= 0)
return;
- for (i = 0; i <= kvnsw; ++i) {
+ for (i = (kvnsw == 1 ? 0 : kvnsw); i >= 0; i--) {
+ name = i == kvnsw ? "Total" : kvmsw[i].ksw_devname;
+ mvwprintw(wnd, 1 + i, 0, "%-*.*s", pathlen, pathlen - 1, name);
+
sysputpage(wnd, i + 1, pathlen, 5, kvmsw[i].ksw_total, 0);
sysputpage(wnd, i + 1, pathlen + 5 + 1, 5, kvmsw[i].ksw_used,
0);
@@ -178,4 +177,11 @@
}
wclrtoeol(wnd);
}
+ if (kvnsw == 1)
+ count = 2;
+ else
+ count = 3;
+ proclabel(kvnsw + count);
+ procshow(kvnsw + count, LINES - 5 - (kvnsw + 3) - (DISKHIGHT + 1),
+ kvmsw[kvnsw].ksw_total);
}
diff --git a/usr.bin/systat/sysput.c b/usr.bin/systat/sysput.c
--- a/usr.bin/systat/sysput.c
+++ b/usr.bin/systat/sysput.c
@@ -40,6 +40,22 @@
#include "systat.h"
#include "extern.h"
+static int page_shift();
+
+uint64_t
+byte_to_page(uint64_t size)
+{
+
+ return (size >> page_shift());
+}
+
+uint64_t
+page_to_byte(uint64_t size)
+{
+
+ return (size << page_shift());
+}
+
void
sysputspaces(WINDOW *wd, int row, int col, int width)
{
@@ -104,15 +120,16 @@
sysputuint64(wd, row, col, width, val, flags);
}
-static int
-calc_page_shift()
+int
+page_shift()
{
u_int page_size;
- int shifts;
+ static int shifts = 0;
- shifts = 0;
+ if (shifts != 0)
+ return (shifts);
GETSYSCTL("vm.stats.vm.v_page_size", page_size);
- for(; page_size > 1; page_size >>= 1)
+ for (; page_size > 1; page_size >>= 1)
shifts++;
return shifts;
}
@@ -120,10 +137,6 @@
void
sysputpage(WINDOW *wd, int row, int col, int width, uint64_t pages, int flags)
{
- static int shifts = 0;
- if (shifts == 0)
- shifts = calc_page_shift();
- pages <<= shifts;
- sysputuint64(wd, row, col, width, pages, flags);
+ sysputuint64(wd, row, col, width, page_to_byte(pages), flags);
}
diff --git a/usr.bin/systat/systat.h b/usr.bin/systat/systat.h
--- a/usr.bin/systat/systat.h
+++ b/usr.bin/systat/systat.h
@@ -33,6 +33,7 @@
*/
#include <curses.h>
+#include <sys/stdint.h>
struct cmdtab {
const char *c_name; /* command name */
@@ -69,6 +70,9 @@
#define NPTR(indx) (void *)NVAL((indx))
#define NREAD(indx, buf, len) kvm_ckread(NPTR((indx)), (buf), (len))
+extern uint64_t byte_to_page(uint64_t size);
+extern uint64_t page_to_byte(uint64_t size);
+
extern void putint(int, int, int, int);
extern void putfloat(double, int, int, int, int, int);
extern void putlongdouble(long double, int, int, int, int, int);
diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1
--- a/usr.bin/systat/systat.1
+++ b/usr.bin/systat/systat.1
@@ -279,9 +279,11 @@
.El
.It Ic swap
Show information about swap space usage on all the
-swap areas compiled into the kernel.
-The first column is the device name of the partition.
-The next column is the total space available in the partition.
+swap areas compiled into the kernel and processes that are swapped out
+and a summary of disk activity.
+.Pp
+The swap areas are displayed first with their name, sizes and
+percentage usage.
The
.Ar Used
column indicates the total blocks used so far;
@@ -289,6 +291,37 @@
If there are more than one swap partition in use,
a total line is also shown.
Areas known to the kernel, but not in use are shown as not available.
+.Pp
+Below the swap space statistics,
+processes are listed in order of higher swap vm object counts.
+Pid, username, a part of command line, the total number of swap objects
+in bytes, the size of process, and per-process swap usage percentage and
+per-system swap space percentage.
+A default vm object is converted to a swap vm objects when paging
+out to swap space the first time.
+Even if such a swap object is paged-in,
+the object remains as a swap object.
+Under some circumstances, the number of swap objects
+may be higher than actual swap space usage.
+One example is when
+.Dl $ swapoff -a
+is run.
+.Pp
+At the bottom left is the disk usage display.
+It reports the number of
+kilobytes per transaction, transactions per second, megabytes
+per second and the percentage of the time the disk was busy averaged
+over the refresh period of the display (by default, five seconds).
+The system keeps statistics on most every storage device.
+In general, up
+to seven devices are displayed.
+The devices displayed by default are the
+first devices in the kernel's device list.
+See
+.Xr devstat 3
+and
+.Xr devstat 9
+for details on the devstat system.
.It Ic vmstat
Take over the entire display and show a (rather crowded) compendium
of statistics related to virtual memory usage, process scheduling,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jun 19, 9:07 PM (16 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34097582
Default Alt Text
D29754.id87399.diff (14 KB)
Attached To
Mode
D29754: Augment systat(1) -swap to display large swap space processes
Attached
Detach File
Event Timeline
Log In to Comment