wmmemload: Use sysctl to get memory usage in FreeBSD.
Previously, kvm_read was used to get the memory usage in FreeBSD. However, this has been deprecated in favor of sysctl. This patch implements this change. Some work had previously been done in this direction, as could be seen in the file src/mem_freebsd_sysctl.c. Since this file is no longer needed, it has been removed. Additionally, some formatting has been done on the remaining older code for a more consistent style.
This commit is contained in:
parent
ba72863015
commit
a473280ab9
3 changed files with 103 additions and 151 deletions
|
@ -14,7 +14,6 @@ wmmemload_SOURCES = \
|
||||||
EXTRA_wmmemload_SOURCES = \
|
EXTRA_wmmemload_SOURCES = \
|
||||||
mem_linux.c \
|
mem_linux.c \
|
||||||
mem_freebsd.c \
|
mem_freebsd.c \
|
||||||
mem_freebsd_sysctl.c \
|
|
||||||
mem_openbsd.c \
|
mem_openbsd.c \
|
||||||
mem_solaris.c
|
mem_solaris.c
|
||||||
|
|
||||||
|
|
|
@ -13,40 +13,27 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
|
||||||
#include <kvm.h>
|
#include <kvm.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/vmmeter.h>
|
#include <sys/errno.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
static kvm_t *kvm_data = NULL;
|
static kvm_t *kvm_data;
|
||||||
static int pageshift;
|
|
||||||
static struct nlist nlst[] = { {"_cp_time"}, {"_cnt"}, {0} };
|
|
||||||
|
|
||||||
/* initialize function */
|
/* initialize function */
|
||||||
void mem_init(void)
|
void mem_init(void)
|
||||||
{
|
{
|
||||||
int pagesize = getpagesize();
|
|
||||||
pageshift = 0;
|
|
||||||
|
|
||||||
while (pagesize > 1) {
|
|
||||||
pageshift++;
|
|
||||||
pagesize >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
kvm_data = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open");
|
kvm_data = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open");
|
||||||
|
|
||||||
if (kvm_data == NULL) {
|
if (kvm_data == NULL) {
|
||||||
fprintf(stderr, "can't open kernel virtual memory");
|
fprintf(stderr, "can't open kernel virtual memory");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
kvm_nlist(kvm_data, nlst);
|
|
||||||
|
|
||||||
if (nlst[0].n_type == 0 || nlst[1].n_type == 0) {
|
|
||||||
fprintf(stderr, "error extracting symbols");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* drop setgid & setuid (the latter should not be there really) */
|
/* drop setgid & setuid (the latter should not be there really) */
|
||||||
seteuid(getuid());
|
seteuid(getuid());
|
||||||
setegid(getgid());
|
setegid(getgid());
|
||||||
|
@ -55,36 +42,64 @@ void mem_init(void)
|
||||||
fprintf(stderr, "unable to drop privileges");
|
fprintf(stderr, "unable to drop privileges");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
|
||||||
|
|
||||||
|
static void getsysctl(const char *name, void *ptr, size_t len)
|
||||||
|
{
|
||||||
|
size_t nlen = len;
|
||||||
|
|
||||||
|
if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
|
||||||
|
fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name,
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (nlen != len) {
|
||||||
|
fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n",
|
||||||
|
name, (unsigned long)len, (unsigned long)nlen);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* return mem/swap usage in percent 0 to 100 */
|
/* return mem/swap usage in percent 0 to 100 */
|
||||||
void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
|
void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
|
||||||
{
|
{
|
||||||
struct vmmeter vm;
|
u_int mtotal, mwired, mcached, mfree, mused;
|
||||||
int bufspace;
|
#ifdef DEBUG
|
||||||
|
u_int pagesize;
|
||||||
|
#endif
|
||||||
|
u_int new_swappgsin, new_swappgsout;
|
||||||
static int swap_firsttime = 1;
|
static int swap_firsttime = 1;
|
||||||
static int swappgsin = -1;
|
static int swappgsin = -1;
|
||||||
static int swappgsout = -1;
|
static int swappgsout = -1;
|
||||||
static int swapmax = 0, swapused = 0;
|
static int swapmax, swapused;
|
||||||
time_t cur_time;
|
time_t cur_time;
|
||||||
static time_t last_time_swap = 0;
|
static time_t last_time_swap;
|
||||||
u_int mused;
|
|
||||||
|
|
||||||
/* get mem usage */
|
/* get mem usage */
|
||||||
if (kvm_read(kvm_data, nlst[0].n_value, &bufspace, sizeof(bufspace)) !=
|
GETSYSCTL("vm.stats.vm.v_page_count", mtotal);
|
||||||
sizeof(bufspace))
|
GETSYSCTL("vm.stats.vm.v_wire_count", mwired);
|
||||||
exit(1);
|
GETSYSCTL("vm.stats.vm.v_cache_count", mcached);
|
||||||
if (kvm_read(kvm_data, nlst[1].n_value, &vm, sizeof(vm)) != sizeof(vm))
|
GETSYSCTL("vm.stats.vm.v_free_count", mfree);
|
||||||
exit(1);
|
#ifdef DEBUG
|
||||||
|
GETSYSCTL("hw.pagesize", pagesize);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* get swap usage */
|
/* get swap usage */
|
||||||
/* only calculate when first time or when changes took place */
|
/* only calculate when first time or when changes took place */
|
||||||
/* do not call it more than 1 time per 2 seconds */
|
/* do not call it more than 1 time per 2 seconds */
|
||||||
/* otherwise it can eat up to 50% of CPU time on heavy swap activity */
|
/* otherwise it can eat up to 50% of CPU time on heavy swap activity */
|
||||||
cur_time = time(NULL);
|
cur_time = time(NULL);
|
||||||
|
|
||||||
|
GETSYSCTL("vm.stats.vm.v_swappgsin", new_swappgsin);
|
||||||
|
GETSYSCTL("vm.stats.vm.v_swappgsout", new_swappgsout);
|
||||||
|
|
||||||
if (swap_firsttime ||
|
if (swap_firsttime ||
|
||||||
(((vm.v_swappgsin > swappgsin) || (vm.v_swappgsout > swappgsout))
|
(((new_swappgsin > swappgsin) || (new_swappgsout > swappgsout))
|
||||||
&& cur_time > last_time_swap + 1)) {
|
&& cur_time > last_time_swap + 1)) {
|
||||||
|
|
||||||
struct kvm_swap swap;
|
struct kvm_swap swap;
|
||||||
|
@ -102,27 +117,28 @@ void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
|
||||||
swap_firsttime = 0;
|
swap_firsttime = 0;
|
||||||
last_time_swap = cur_time;
|
last_time_swap = cur_time;
|
||||||
}
|
}
|
||||||
swappgsin = vm.v_swappgsin;
|
|
||||||
swappgsout = vm.v_swappgsout;
|
swappgsin = new_swappgsin;
|
||||||
|
swappgsout = new_swappgsout;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf ("-------------------\n");
|
printf("-------------------\n");
|
||||||
printf ("total:%10d\n", vm.v_page_count * vm.v_page_size);
|
printf("total:%10d\n", mtotal * pagesize);
|
||||||
printf ("free :%10d\n", vm.v_free_count * vm.v_page_size);
|
printf("free :%10d\n", mfree * pagesize);
|
||||||
printf ("act :%10d\n", vm.v_active_count * vm.v_page_size);
|
printf("wired:%10d\n", mwired * pagesize);
|
||||||
printf ("inact:%10d\n", vm.v_inactive_count * vm.v_page_size);
|
printf("cache:%10d\n", mcached * pagesize);
|
||||||
printf ("wired:%10d\n", vm.v_wire_count * vm.v_page_size);
|
printf("-------------------\n");
|
||||||
printf ("cache:%10d\n", vm.v_cache_count * vm.v_page_size);
|
|
||||||
printf ("-------------------\n");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* calc mem/swap usage in percent */
|
/* calc mem/swap usage in percent */
|
||||||
mused = vm.v_page_count - vm.v_free_count;
|
mused = mtotal - mfree;
|
||||||
if (opts->ignore_wired) mused -= vm.v_wire_count;
|
if (opts->ignore_wired)
|
||||||
if (opts->ignore_cached) mused -= vm.v_cache_count;
|
mused -= mwired;
|
||||||
|
if (opts->ignore_cached)
|
||||||
*per_mem = 100 * (double) mused / (double) vm.v_page_count;
|
mused -= mcached;
|
||||||
|
*per_mem = 100 * (double) mused / (double) mtotal;
|
||||||
*per_swap = 100 * (double) swapused / (double) swapmax;
|
*per_swap = 100 * (double) swapused / (double) swapmax;
|
||||||
|
|
||||||
if (*per_mem > 97) *per_mem = 100;
|
if (*per_mem > 97)
|
||||||
|
*per_mem = 100;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* mem_freebsd.c - module to get memory/swap usages in percent, for FreeBSD
|
|
||||||
*
|
|
||||||
* Copyright (c) 2001, 2002 Seiichi SATO <ssato@sh.rim.or.jp>
|
|
||||||
*
|
|
||||||
* licensed under the GPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "mem.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <vm/vm_param.h>
|
|
||||||
#include <sys/vmmeter.h>
|
|
||||||
|
|
||||||
/* initialize function */
|
|
||||||
void mem_init(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return mem/swap usage in percent 0 to 100 */
|
|
||||||
void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
|
|
||||||
{
|
|
||||||
|
|
||||||
struct vmtotal vm;
|
|
||||||
size_t size = sizeof(vm);
|
|
||||||
static int mib[] = { CTL_VM, VM_METER };
|
|
||||||
|
|
||||||
/* get mem usage */
|
|
||||||
if (sysctl(mib, 2, &vm, &size, NULL, 0) < 0)
|
|
||||||
bzero(&vm, sizeof(vm));
|
|
||||||
|
|
||||||
/* calc mem usage in percent */
|
|
||||||
/* FIXME: the total usage(t_rm and t_free) is incorrect?? */
|
|
||||||
if (vm.t_rm > 0)
|
|
||||||
*per_mem = 100 * (double) vm.t_rm / (double) (vm.t_rm + vm.t_free);
|
|
||||||
if (*per_mem > 95)
|
|
||||||
*per_mem = 100;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("t_vm total virtual memory %6lu\n", vm.t_vm);
|
|
||||||
printf("t_rm total real memory in use %6lu\n", vm.t_rm);
|
|
||||||
printf("t_arm active real memory %6lu\n", vm.t_arm);
|
|
||||||
printf("t_rmshr shared real memory %6lu\n", vm.t_rmshr);
|
|
||||||
printf("t_armshr active shared real memory %6lu\n", vm.t_armshr);
|
|
||||||
printf("t_free free memory pages %6lu\n", vm.t_free);
|
|
||||||
printf("--------------------------------------------\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* get swap usage */
|
|
||||||
/* not written yet.. can i get swap usage via sysctl? */
|
|
||||||
|
|
||||||
*per_swap = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
Loading…
Reference in a new issue