You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeutils/ksim/systeminfo.cpp

278 lines
6.2 KiB

/* System Information
*
* Copyright (C) 2001 Robbie Ward <linuxphreak@gmx.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "systeminfo.h"
#ifdef __linux__
#include <sys/sysinfo.h>
#include <linux/kernel.h>
#endif
#ifdef HAVE_SYS_LOADAVG_H
#include <sys/loadavg.h>
#endif
#ifdef __FreeBSD__
#include <osreldate.h>
#include <kvm.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/conf.h>
#if __FreeBSD_version < 400000
#include <sys/rlist.h>
#endif
#include <sys/vmmeter.h>
#include <sys/sysctl.h>
#include <vm/vm_param.h>
#include <iomanip>
#include <iostream>
#endif
// Some global vars
// expand as needed for other platforms
int System::bytesToMegs( unsigned long value )
{
#ifdef __linux__
return ((((value / 1024) >> 10) | 11) + 1);
#endif
#ifdef __FreeBSD__
return (((value) + (1 << 19)) >> 20);
#endif
}
System * System::m_self = 0; // initialize pointer
System & System::self()
{
if ( !m_self )
{
m_self = new System;
atexit( System::cleanup );
}
m_self->updateData();
return *m_self;
}
void System::cleanup()
{
if ( !m_self )
return;
delete m_self;
m_self = 0;
}
double System::loadAverage( int load ) const
{
int value = --load;
return loadAverages()[ value > 2 ? 2 : value ];
}
System::System()
{
m_loads[ 0 ] = 0;
m_loads[ 1 ] = 0;
m_loads[ 2 ] = 0;
m_uptime = 0;
m_totalram = 0;
m_usedram = 0;
m_freeram = 0;
m_sharedram = 0;
m_bufferram = 0;
m_cacheram = 0;
m_totalhigh = 0;
m_freehigh = 0;
m_totalswap = 0;
m_usedswap = 0;
m_freeswap = 0;
m_procs = 0;
m_self = this;
}
System::~System()
{
}
void System::updateData()
{
#ifdef __linux__
struct sysinfo system;
if (sysinfo(&system) < 0) {
fprintf(stderr, "Error calling sysinfo()\n");
return;
}
m_uptime = system.uptime;
m_totalram = system.totalram;
m_sharedram = system.sharedram;
m_bufferram = system.bufferram;
m_usedram = m_totalram - m_freeram;
#ifdef HAVE_SYSINFO_HIGH
m_totalhigh = system.totalhigh;
m_freehigh = system.freehigh;
#else
#ifdef __GNUC__
#warning "TODO: find alternative way to get total high and freehigh"
#endif
#endif
m_totalswap = system.totalswap;
m_freeswap = system.freeswap;
m_procs = system.procs;
m_cacheram = 0;
FILE *file = fopen("/proc/meminfo", "r");
char buffer[70];
if (file) {
while (fgets(buffer, sizeof(buffer), file)) {
sscanf(buffer, "Mem: %*d %*d %*d %*d %*d %lu", &m_cacheram);
if (m_cacheram != 0)
break;
}
fclose(file);
}
m_freeram = system.freeram;
#endif
#ifdef __FreeBSD__
struct timeval bootTime;
size_t size = sizeof(bootTime);
if (sysctlbyname("kern.boottime",
&bootTime, &size, NULL, 0) != -1 && bootTime.tv_sec != 0) {
m_uptime = time(0) - bootTime.tv_sec + 30;
}
char buf[80];
char *used;
char *total;
FILE *pipe;
static int psize = 0, pshift = 0;
static int name2oid[2] = { 0, 3 };
struct vmtotal vmt;
size_t vmtLength = sizeof(vmt);
static char name[] = "vfs.bufspace";
static int oidBufspace[CTL_MAXNAME + 2];
static size_t oidBufspaceLength = sizeof(oidBufspace);
size_t bufspaceLength = sizeof(int);
static int initialized = 0;
unsigned long memXUsed, memTotal;
size_t memLength = sizeof(memTotal);
if (pshift == 0) {
psize = getpagesize();
while (psize > 1) {
++pshift;
psize >>= 1;
}
}
unsigned long xused1, xused2;
size_t xused1Length = sizeof(xused1);
size_t xused2Length = sizeof(xused2);
if (sysctlbyname("vm.stats.vm.v_active_count", &xused1, &xused1Length, NULL, 0) == 0
&& sysctlbyname("vm.stats.vm.v_inactive_count", &xused2, &xused2Length, NULL, 0) == 0) {
memXUsed = (xused1 + xused2) << pshift;
}
unsigned long cacheRam;
size_t cacheSize = sizeof(cacheRam);
if (sysctlbyname("vm.stats.vm.v_active_count", &cacheRam, &cacheSize, NULL, 0) == 0) {
m_cacheram = cacheRam << pshift;
}
if (!m_totalram && sysctlbyname("hw.physmem", &memTotal, &memLength, NULL, 0) == 0)
m_totalram = memTotal;
if (sysctlbyname("vm.meter", &vmt, &vmtLength, NULL, 0) == 0)
m_sharedram = vmt.t_rmshr << pshift;
if (!initialized) {
if (sysctl(name2oid, 2, oidBufspace, &oidBufspaceLength,
name, strlen(name)) < 0)
return;
oidBufspaceLength /= sizeof(int);
++initialized;
}
if (sysctl(oidBufspace, oidBufspaceLength,
&m_bufferram, &bufspaceLength, 0, 0) < 0)
return;
m_usedram = memXUsed - m_bufferram - m_cacheram;
m_freeram = memTotal - m_usedram;
//TODO: get the total and free high mem values
m_totalhigh = 0;
m_freehigh = 0;
if ((pipe = popen("/usr/sbin/swapinfo -k", "r")) == 0) {
fprintf(stderr, "Error reading swap info\n");
m_freeswap = m_totalswap = 1;
return;
}
fgets(buf, sizeof(buf), pipe);
fgets(buf, sizeof(buf), pipe);
fgets(buf, sizeof(buf), pipe);
fgets(buf, sizeof(buf), pipe);
pclose(pipe);
strtok(buf, " ");
total = strtok(NULL, " ");
used = strtok(NULL, " ");
unsigned long usedSwap = atol(used) * 1024;
m_totalswap = atol(total) * 1024;
m_freeswap = m_totalswap - usedSwap;
//TODO: get amount of procs
m_procs = 0;
#endif
#ifdef HAVE_GETLOADAVG
double load[3];
if (getloadavg(load, 3) != -1) {
m_loads[0] = load[0];
m_loads[1] = load[1];
m_loads[2] = load[2];
}
#else
#warning "TODO: Find an alternative method for getloadavg"
#endif
m_usedswap = m_totalswap - m_freeswap;
}