diff --git a/ksysguardd/Linux/stat.c b/ksysguardd/Linux/stat.c index 534a4654..65d08b30 100644 --- a/ksysguardd/Linux/stat.c +++ b/ksysguardd/Linux/stat.c @@ -1,1087 +1,1088 @@ /* KSysGuard, the KDE System Guard Copyright (c) 1999, 2000 Chris Schlaeger This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. 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. */ /* * stat.c is used to read from /proc/[pid]/stat */ #include #include #include #include #include #include #include #include #include #include "Command.h" #include "ksysguardd.h" #include "stat.h" typedef struct { /* A CPU can be loaded with user processes, reniced processes and * system processes. Unused processing time is called idle load. * These variable store the percentage of each load type. */ float userLoad; float niceLoad; float sysLoad; float idleLoad; float waitLoad; /* To calculate the loads we need to remember the tick values for each * load type. */ unsigned long userTicks; unsigned long niceTicks; unsigned long sysTicks; unsigned long idleTicks; unsigned long waitTicks; } CPULoadInfo; typedef struct { unsigned long delta; unsigned long old; } DiskLoadSample; typedef struct { /* 5 types of samples are taken: total, rio, wio, rBlk, wBlk */ DiskLoadSample s[ 5 ]; } DiskLoadInfo; typedef struct DiskIOInfo { int major; int minor; char* devname; int alive; DiskLoadSample total; DiskLoadSample rio; DiskLoadSample wio; DiskLoadSample rblk; DiskLoadSample wblk; struct DiskIOInfo* next; } DiskIOInfo; #define DISKDEVNAMELEN 16 static int StatDirty = 0; /* We have observed deviations of up to 5% in the accuracy of the timer * interrupts. So we try to measure the interrupt interval and use this * value to calculate timing dependant values. */ static float timeInterval = 0; static struct timeval lastSampling; static struct timeval currSampling; static struct SensorModul* StatSM; static CPULoadInfo CPULoad; static CPULoadInfo* SMPLoad = 0; static unsigned CPUCount = 0; static DiskLoadInfo* DiskLoad = 0; static unsigned DiskCount = 0; static DiskIOInfo* DiskIO = 0; static unsigned long PageIn = 0; static unsigned long OldPageIn = 0; static unsigned long PageOut = 0; static unsigned long OldPageOut = 0; static unsigned long Ctxt = 0; static unsigned long OldCtxt = 0; static unsigned int NumOfInts = 0; static unsigned long* OldIntr = 0; static unsigned long* Intr = 0; static int initStatDisk( char* tag, char* buf, const char* label, const char* shortLabel, int idx, cmdExecutor ex, cmdExecutor iq ); static void updateCPULoad( const char* line, CPULoadInfo* load ); static int process24Disk( char* tag, char* buf, const char* label, int idx ); static void processStat( void ); static int process24DiskIO( const char* buf ); static void cleanup24DiskList( void ); static int initStatDisk( char* tag, char* buf, const char* label, const char* shortLabel, int idx, cmdExecutor ex, cmdExecutor iq ) { char sensorName[ 128 ]; gettimeofday( &lastSampling, 0 ); if ( strcmp( label, tag ) == 0 ) { unsigned int i; buf = buf + strlen( label ) + 1; for ( i = 0; i < DiskCount; ++i ) { sscanf( buf, "%lu", &DiskLoad[ i ].s[ idx ].old ); while ( *buf && isblank( *buf++ ) ); while ( *buf && isdigit( *buf++ ) ); sprintf( sensorName, "disk/disk%d/%s", i, shortLabel ); registerMonitor( sensorName, "float", ex, iq, StatSM ); } return 1; } return 0; } /** * updateCPULoad * * Parses the total cpu status line from /proc/stat */ static void updateCPULoad( const char* line, CPULoadInfo* load ) { unsigned long currUserTicks, currSysTicks, currNiceTicks; unsigned long currIdleTicks, currWaitTicks, totalTicks; if(sscanf( line, "%*s %lu %lu %lu %lu %lu", &currUserTicks, &currNiceTicks, &currSysTicks, &currIdleTicks, &currWaitTicks ) != 5) { return; } totalTicks = ( currUserTicks - load->userTicks ) + ( currSysTicks - load->sysTicks ) + ( currNiceTicks - load->niceTicks ) + ( currIdleTicks - load->idleTicks ) + ( currWaitTicks - load->waitTicks ); if ( totalTicks > 10 ) { load->userLoad = ( 100.0 * ( currUserTicks - load->userTicks ) ) / totalTicks; load->sysLoad = ( 100.0 * ( currSysTicks - load->sysTicks ) ) / totalTicks; load->niceLoad = ( 100.0 * ( currNiceTicks - load->niceTicks ) ) / totalTicks; load->idleLoad = ( 100.0 * ( currIdleTicks - load->idleTicks ) ) / totalTicks; load->waitLoad = ( 100.0 * ( currWaitTicks - load->waitTicks ) ) / totalTicks; } else load->userLoad = load->sysLoad = load->niceLoad = load->idleLoad = load->waitLoad = 0.0; load->userTicks = currUserTicks; load->sysTicks = currSysTicks; load->niceTicks = currNiceTicks; load->idleTicks = currIdleTicks; load->waitTicks = currWaitTicks; } static int process24Disk( char* tag, char* buf, const char* label, int idx ) { if ( strcmp( label, tag ) == 0 ) { unsigned long val; unsigned int i; buf = buf + strlen( label ) + 1; for ( i = 0; i < DiskCount; ++i ) { sscanf( buf, "%lu", &val ); while ( *buf && isblank( *buf++ ) ); while ( *buf && isdigit( *buf++ ) ); DiskLoad[ i ].s[ idx ].delta = val - DiskLoad[ i ].s[ idx ].old; DiskLoad[ i ].s[ idx ].old = val; } return 1; } return 0; } static int process24DiskIO( const char* buf ) { /* Process disk_io lines as provided by 2.4.x kernels. * disk_io: (2,0):(3,3,6,0,0) (3,0):(1413012,511622,12155382,901390,26486215) */ int major, minor; unsigned long total, rblk, rio, wblk, wio; DiskIOInfo* ptr = DiskIO; DiskIOInfo* last = 0; char sensorName[ 128 ]; const char* p; p = buf + strlen( "disk_io: " ); while ( p && *p ) { if ( sscanf( p, "(%d,%d):(%lu,%lu,%lu,%lu,%lu)", &major, &minor, &total, &rio, &rblk, &wio, &wblk ) != 7 ) return -1; last = 0; ptr = DiskIO; while ( ptr ) { if ( ptr->major == major && ptr->minor == minor ) { /* The IO device has already been registered. */ ptr->total.delta = total - ptr->total.old; ptr->total.old = total; ptr->rio.delta = rio - ptr->rio.old; ptr->rio.old = rio; ptr->wio.delta = wio - ptr->wio.old; ptr->wio.old = wio; ptr->rblk.delta = rblk - ptr->rblk.old; ptr->rblk.old = rblk; ptr->wblk.delta = wblk - ptr->wblk.old; ptr->wblk.old = wblk; ptr->alive = 1; break; } last = ptr; ptr = ptr->next; } if ( !ptr ) { /* The IO device has not been registered yet. We need to add it. */ ptr = (DiskIOInfo*)malloc( sizeof( DiskIOInfo ) ); ptr->major = major; ptr->minor = minor; /* 2.6 gives us a nice device name. On 2.4 we get nothing */ ptr->devname = (char *)malloc( DISKDEVNAMELEN ); memset( ptr->devname, 0, DISKDEVNAMELEN ); ptr->total.delta = 0; ptr->total.old = total; ptr->rio.delta = 0; ptr->rio.old = rio; ptr->wio.delta = 0; ptr->wio.old = wio; ptr->rblk.delta = 0; ptr->rblk.old = rblk; ptr->wblk.delta = 0; ptr->wblk.old = wblk; ptr->alive = 1; ptr->next = 0; if ( last ) { /* Append new entry at end of list. */ last->next = ptr; } else { /* List is empty, so we insert the fist element into the list. */ DiskIO = ptr; } sprintf( sensorName, "disk/%s_(%d:%d)24/total", ptr->devname, major, minor ); registerMonitor( sensorName, "float", print24DiskIO, print24DiskIOInfo, StatSM ); sprintf( sensorName, "disk/%s_(%d:%d)24/rio", ptr->devname, major, minor ); registerMonitor( sensorName, "float", print24DiskIO, print24DiskIOInfo, StatSM ); sprintf( sensorName, "disk/%s_(%d:%d)24/wio", ptr->devname, major, minor ); registerMonitor( sensorName, "float", print24DiskIO, print24DiskIOInfo, StatSM ); sprintf( sensorName, "disk/%s_(%d:%d)24/rblk", ptr->devname, major, minor ); registerMonitor( sensorName, "float", print24DiskIO, print24DiskIOInfo, StatSM ); sprintf( sensorName, "disk/%s_(%d:%d)24/wblk", ptr->devname, major, minor ); registerMonitor( sensorName, "float", print24DiskIO, print24DiskIOInfo, StatSM ); } /* Move p after the second ')'. We can safely assume that * those two ')' exist. */ p = strchr( p, ')' ) + 1; p = strchr( p, ')' ) + 1; if ( p && *p ) p = strchr( p, '(' ); } return 0; } static void cleanup24DiskList( void ) { DiskIOInfo* ptr = DiskIO; DiskIOInfo* last = 0; while ( ptr ) { if ( ptr->alive == 0 ) { DiskIOInfo* newPtr; char sensorName[ 128 ]; /* Disk device has disappeared. We have to remove it from * the list and unregister the monitors. */ sprintf( sensorName, "disk/%s_(%d:%d)24/total", ptr->devname, ptr->major, ptr->minor ); removeMonitor( sensorName ); sprintf( sensorName, "disk/%s_(%d:%d)24/rio", ptr->devname, ptr->major, ptr->minor ); removeMonitor( sensorName ); sprintf( sensorName, "disk/%s_(%d:%d)24/wio", ptr->devname, ptr->major, ptr->minor ); removeMonitor( sensorName ); sprintf( sensorName, "disk/%s_(%d:%d)24/rblk", ptr->devname, ptr->major, ptr->minor ); removeMonitor( sensorName ); sprintf( sensorName, "disk/%s_(%d:%d)24/wblk", ptr->devname, ptr->major, ptr->minor ); removeMonitor( sensorName ); if ( last ) { last->next = ptr->next; newPtr = ptr->next; } else { DiskIO = ptr->next; newPtr = DiskIO; last = 0; } free ( ptr ); ptr = newPtr; } else { ptr->alive = 0; last = ptr; ptr = ptr->next; } } } static void processStat( void ) { char format[ 32 ]; char tagFormat[ 16 ]; char buf[ 1024 ]; char tag[ 32 ]; sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 ); sprintf( tagFormat, "%%%ds", (int)sizeof( tag ) - 1 ); gettimeofday( &currSampling, 0 ); StatDirty = 0; FILE *stat = fopen("/proc/stat", "r"); if(!stat) { print_error( "Cannot open file \'/proc/stat\'!\n" "The kernel needs to be compiled with support\n" "for /proc file system enabled!\n" ); return; } while ( fscanf( stat, format, buf ) == 1 ) { buf[ sizeof( buf ) - 1 ] = '\0'; sscanf( buf, tagFormat, tag ); if ( strcmp( "cpu", tag ) == 0 ) { /* Total CPU load */ updateCPULoad( buf, &CPULoad ); } else if ( strncmp( "cpu", tag, 3 ) == 0 ) { /* Load for each SMP CPU */ int id; sscanf( tag + 3, "%d", &id ); updateCPULoad( buf, &SMPLoad[ id ] ); } else if ( process24Disk( tag, buf, "disk", 0 ) ) { } else if ( process24Disk( tag, buf, "disk_rio", 1 ) ) { } else if ( process24Disk( tag, buf, "disk_wio", 2 ) ) { } else if ( process24Disk( tag, buf, "disk_rblk", 3 ) ) { } else if ( process24Disk( tag, buf, "disk_wblk", 4 ) ) { } else if ( strcmp( "disk_io:", tag ) == 0 ) { process24DiskIO( buf ); } else if ( strcmp( "page", tag ) == 0 ) { unsigned long v1, v2; sscanf( buf + 5, "%lu %lu", &v1, &v2 ); PageIn = v1 - OldPageIn; OldPageIn = v1; PageOut = v2 - OldPageOut; OldPageOut = v2; } else if ( strcmp( "intr", tag ) == 0 ) { unsigned int i = 0; char* p = buf + 5; for ( i = 0; i < NumOfInts; i++ ) { unsigned long val; sscanf( p, "%lu", &val ); Intr[ i ] = val - OldIntr[ i ]; OldIntr[ i ] = val; while ( *p && *p != ' ' ) p++; while ( *p && *p == ' ' ) p++; } } else if ( strcmp( "ctxt", tag ) == 0 ) { unsigned long val; sscanf( buf + 5, "%lu", &val ); Ctxt = val - OldCtxt; OldCtxt = val; } } fclose(stat); /* Read Linux 2.5.x /proc/vmstat */ stat = fopen("/proc/vmstat", "r"); if(stat) { while ( fscanf( stat, format, buf ) == 1 ) { buf[ sizeof( buf ) - 1 ] = '\0'; sscanf( buf, tagFormat, tag ); if ( strcmp( "pgpgin", tag ) == 0 ) { unsigned long v1; sscanf( buf + 7, "%lu", &v1 ); PageIn = v1 - OldPageIn; OldPageIn = v1; } else if ( strcmp( "pgpgout", tag ) == 0 ) { unsigned long v1; sscanf( buf + 7, "%lu", &v1 ); PageOut = v1 - OldPageOut; OldPageOut = v1; } } fclose(stat); } /* save exact time interval between this and the last read of /proc/stat */ timeInterval = currSampling.tv_sec - lastSampling.tv_sec + ( currSampling.tv_usec - lastSampling.tv_usec ) / 1000000.0; lastSampling = currSampling; cleanup24DiskList(); } /* ================================ public part ================================= */ void initStat( struct SensorModul* sm ) { /* The CPU load is calculated from the values in /proc/stat. The cpu * entry contains 7 counters. These counters count the number of ticks * the system has spend on user processes, system processes, nice * processes, idle and IO-wait time, hard and soft interrupts. * * SMP systems will have cpu1 to cpuN lines right after the cpu info. The * format is identical to cpu and reports the information for each cpu. * Linux kernels <= 2.0 do not provide this information! * * The /proc/stat file looks like this: * * cpu * disk 7797 0 0 0 * disk_rio 6889 0 0 0 * disk_wio 908 0 0 0 * disk_rblk 13775 0 0 0 * disk_wblk 1816 0 0 0 * page 27575 1330 * swap 1 0 * intr 50444 38672 2557 0 0 0 0 2 0 2 0 0 3 1429 1 7778 0 * ctxt 54155 * btime 917379184 * processes 347 * * Linux kernel >= 2.4.0 have one or more disk_io: lines instead of * the disk_* lines. * * Linux kernel >= 2.6.x(?) have disk I/O stats in /proc/diskstats * and no disk relevant lines are found in /proc/stat */ char format[ 32 ]; char tagFormat[ 16 ]; char buf[ 1024 ]; char tag[ 32 ]; StatSM = sm; sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 ); sprintf( tagFormat, "%%%ds", (int)sizeof( tag ) - 1 ); FILE *stat = fopen("/proc/stat", "r"); if(!stat) { print_error( "Cannot open file \'/proc/stat\'!\n" "The kernel needs to be compiled with support\n" "for /proc file system enabled!\n" ); return; } while ( fscanf( stat, format, buf ) == 1 ) { buf[ sizeof( buf ) - 1 ] = '\0'; sscanf( buf, tagFormat, tag ); if ( strcmp( "cpu", tag ) == 0 ) { /* Total CPU load */ registerMonitor( "cpu/system/user", "float", printCPUUser, printCPUUserInfo, StatSM ); registerMonitor( "cpu/system/nice", "float", printCPUNice, printCPUNiceInfo, StatSM ); registerMonitor( "cpu/system/sys", "float", printCPUSys, printCPUSysInfo, StatSM ); registerMonitor( "cpu/system/TotalLoad", "float", printCPUTotalLoad, printCPUTotalLoadInfo, StatSM ); registerMonitor( "cpu/system/idle", "float", printCPUIdle, printCPUIdleInfo, StatSM ); registerMonitor( "cpu/system/wait", "float", printCPUWait, printCPUWaitInfo, StatSM ); /* Monitor names changed from kde3 => kde4. Remain compatible with legacy requests when possible. */ registerLegacyMonitor( "cpu/user", "float", printCPUUser, printCPUUserInfo, StatSM ); registerLegacyMonitor( "cpu/nice", "float", printCPUNice, printCPUNiceInfo, StatSM ); registerLegacyMonitor( "cpu/sys", "float", printCPUSys, printCPUSysInfo, StatSM ); registerLegacyMonitor( "cpu/TotalLoad", "float", printCPUTotalLoad, printCPUTotalLoadInfo, StatSM ); registerLegacyMonitor( "cpu/idle", "float", printCPUIdle, printCPUIdleInfo, StatSM ); registerLegacyMonitor( "cpu/wait", "float", printCPUWait, printCPUWaitInfo, StatSM ); } else if ( strncmp( "cpu", tag, 3 ) == 0 ) { char cmdName[ 24 ]; /* Load for each SMP CPU */ int id; sscanf( tag + 3, "%d", &id ); - CPUCount++; + if ( CPUCount < id + 1 ) + CPUCount = id + 1; sprintf( cmdName, "cpu/cpu%d/user", id ); registerMonitor( cmdName, "float", printCPUxUser, printCPUxUserInfo, StatSM ); sprintf( cmdName, "cpu/cpu%d/nice", id ); registerMonitor( cmdName, "float", printCPUxNice, printCPUxNiceInfo, StatSM ); sprintf( cmdName, "cpu/cpu%d/sys", id ); registerMonitor( cmdName, "float", printCPUxSys, printCPUxSysInfo, StatSM ); sprintf( cmdName, "cpu/cpu%d/TotalLoad", id ); registerMonitor( cmdName, "float", printCPUxTotalLoad, printCPUxTotalLoadInfo, StatSM ); sprintf( cmdName, "cpu/cpu%d/idle", id ); registerMonitor( cmdName, "float", printCPUxIdle, printCPUxIdleInfo, StatSM ); sprintf( cmdName, "cpu/cpu%d/wait", id ); registerMonitor( cmdName, "float", printCPUxWait, printCPUxWaitInfo, StatSM ); } else if ( strcmp( "disk", tag ) == 0 ) { unsigned long val; char* b = buf + 5; /* Count the number of registered disks */ for ( DiskCount = 0; *b && sscanf( b, "%lu", &val ) == 1; DiskCount++ ) { while ( *b && isblank( *b++ ) ); while ( *b && isdigit( *b++ ) ); } if ( DiskCount > 0 ) DiskLoad = (DiskLoadInfo*)malloc( sizeof( DiskLoadInfo ) * DiskCount ); initStatDisk( tag, buf, "disk", "disk", 0, print24DiskTotal, print24DiskTotalInfo ); } else if ( initStatDisk( tag, buf, "disk_rio", "rio", 1, print24DiskRIO, print24DiskRIOInfo ) ); else if ( initStatDisk( tag, buf, "disk_wio", "wio", 2, print24DiskWIO, print24DiskWIOInfo ) ); else if ( initStatDisk( tag, buf, "disk_rblk", "rblk", 3, print24DiskRBlk, print24DiskRBlkInfo ) ); else if ( initStatDisk( tag, buf, "disk_wblk", "wblk", 4, print24DiskWBlk, print24DiskWBlkInfo ) ); else if ( strcmp( "disk_io:", tag ) == 0 ) process24DiskIO( buf ); else if ( strcmp( "page", tag ) == 0 ) { sscanf( buf + 5, "%lu %lu", &OldPageIn, &OldPageOut ); registerMonitor( "cpu/pageIn", "float", printPageIn, printPageInInfo, StatSM ); registerMonitor( "cpu/pageOut", "float", printPageOut, printPageOutInfo, StatSM ); } else if ( strcmp( "intr", tag ) == 0 ) { unsigned int i; char cmdName[ 32 ]; char* p = buf + 5; /* Count the number of listed values in the intr line. */ NumOfInts = 0; while ( *p ) if ( *p++ == ' ' ) NumOfInts++; /* It looks like anything above 24 is always 0. So let's just * ignore this for the time being. */ if ( NumOfInts > 25 ) NumOfInts = 25; OldIntr = (unsigned long*)malloc( NumOfInts * sizeof( unsigned long ) ); Intr = (unsigned long*)malloc( NumOfInts * sizeof( unsigned long ) ); i = 0; p = buf + 5; for ( i = 0; p && i < NumOfInts; i++ ) { sscanf( p, "%lu", &OldIntr[ i ] ); while ( *p && *p != ' ' ) p++; while ( *p && *p == ' ' ) p++; sprintf( cmdName, "cpu/interrupts/int%02d", i ); registerMonitor( cmdName, "float", printInterruptx, printInterruptxInfo, StatSM ); } } else if ( strcmp( "ctxt", tag ) == 0 ) { sscanf( buf + 5, "%lu", &OldCtxt ); registerMonitor( "cpu/context", "float", printCtxt, printCtxtInfo, StatSM ); } } fclose(stat); stat = fopen("/proc/vmstat", "r"); if(!stat) { print_error( "Cannot open file \'/proc/vmstat\'\n"); } else { while ( fscanf( stat, format, buf ) == 1 ) { buf[ sizeof( buf ) - 1 ] = '\0'; sscanf( buf, tagFormat, tag ); if ( strcmp( "pgpgin", tag ) == 0 ) { sscanf( buf + 7, "%lu", &OldPageIn ); registerMonitor( "cpu/pageIn", "float", printPageIn, printPageInInfo, StatSM ); } else if ( strcmp( "pgpgout", tag ) == 0 ) { sscanf( buf + 7, "%lu", &OldPageOut ); registerMonitor( "cpu/pageOut", "float", printPageOut, printPageOutInfo, StatSM ); } } fclose(stat); } if ( CPUCount > 0 ) SMPLoad = (CPULoadInfo*)calloc( CPUCount, sizeof( CPULoadInfo ) ); /* Call processStat to eliminate initial peek values. */ processStat(); } void exitStat( void ) { free( DiskLoad ); DiskLoad = 0; free( SMPLoad ); SMPLoad = 0; free( OldIntr ); OldIntr = 0; free( Intr ); Intr = 0; removeMonitor("cpu/system/user"); removeMonitor("cpu/system/nice"); removeMonitor("cpu/system/sys"); removeMonitor("cpu/system/idle"); /* Todo: Dynamically registered monitors (per cpu, per disk) are not removed yet) */ /* These were registered as legacy monitors */ removeMonitor("cpu/user"); removeMonitor("cpu/nice"); removeMonitor("cpu/sys"); removeMonitor("cpu/idle"); } int updateStat( void ) { StatDirty = 1; return 0; } void printCPUUser( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", CPULoad.userLoad ); } void printCPUUserInfo( const char* cmd ) { (void)cmd; output( "CPU User Load\t0\t100\t%%\n" ); } void printCPUNice( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", CPULoad.niceLoad ); } void printCPUNiceInfo( const char* cmd ) { (void)cmd; output( "CPU Nice Load\t0\t100\t%%\n" ); } void printCPUSys( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", CPULoad.sysLoad ); } void printCPUSysInfo( const char* cmd ) { (void)cmd; output( "CPU System Load\t0\t100\t%%\n" ); } void printCPUTotalLoad( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", CPULoad.userLoad + CPULoad.sysLoad + CPULoad.niceLoad + CPULoad.waitLoad ); } void printCPUTotalLoadInfo( const char* cmd ) { (void)cmd; output( "CPU Total Load\t0\t100\t%%\n" ); } void printCPUIdle( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", CPULoad.idleLoad ); } void printCPUIdleInfo( const char* cmd ) { (void)cmd; output( "CPU Idle Load\t0\t100\t%%\n" ); } void printCPUWait( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", CPULoad.waitLoad ); } void printCPUWaitInfo( const char* cmd ) { (void)cmd; output( "CPU Wait Load\t0\t100\t%%\n" ); } void printCPUxUser( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 7, "%d", &id ); output( "%f\n", SMPLoad[ id ].userLoad ); } void printCPUxUserInfo( const char* cmd ) { int id; sscanf( cmd + 7, "%d", &id ); output( "CPU %d User Load\t0\t100\t%%\n", id+1 ); } void printCPUxNice( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 7, "%d", &id ); output( "%f\n", SMPLoad[ id ].niceLoad ); } void printCPUxNiceInfo( const char* cmd ) { int id; sscanf( cmd + 7, "%d", &id ); output( "CPU %d Nice Load\t0\t100\t%%\n", id+1 ); } void printCPUxSys( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 7, "%d", &id ); output( "%f\n", SMPLoad[ id ].sysLoad ); } void printCPUxSysInfo( const char* cmd ) { int id; sscanf( cmd + 7, "%d", &id ); output( "CPU %d System Load\t0\t100\t%%\n", id+1 ); } void printCPUxTotalLoad( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 7, "%d", &id ); output( "%f\n", SMPLoad[ id ].userLoad + SMPLoad[ id ].sysLoad + SMPLoad[ id ].niceLoad + SMPLoad[ id ].waitLoad ); } void printCPUxTotalLoadInfo( const char* cmd ) { int id; sscanf( cmd + 7, "%d", &id ); output( "CPU %d\t0\t100\t%%\n", id+1 ); } void printCPUxIdle( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 7, "%d", &id ); output( "%f\n", SMPLoad[ id ].idleLoad ); } void printCPUxIdleInfo( const char* cmd ) { int id; sscanf( cmd + 7, "%d", &id ); output( "CPU %d Idle Load\t0\t100\t%%\n", id+1 ); } void printCPUxWait( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 7, "%d", &id ); output( "%f\n", SMPLoad[ id ].waitLoad ); } void printCPUxWaitInfo( const char* cmd ) { int id; sscanf( cmd + 7, "%d", &id ); output( "CPU %d Wait Load\t0\t100\t%%\n", id+1 ); } void print24DiskTotal( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 9, "%d", &id ); output( "%f\n", (float)( DiskLoad[ id ].s[ 0 ].delta / timeInterval ) ); } void print24DiskTotalInfo( const char* cmd ) { int id; sscanf( cmd + 9, "%d", &id ); output( "Disk %d Total Load\t0\t0\tKB/s\n", id ); } void print24DiskRIO( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 9, "%d", &id ); output( "%f\n", (float)( DiskLoad[ id ].s[ 1 ].delta / timeInterval ) ); } void print24DiskRIOInfo( const char* cmd ) { int id; sscanf( cmd + 9, "%d", &id ); output( "Disk %d Read\t0\t0\tKB/s\n", id ); } void print24DiskWIO( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 9, "%d", &id ); output( "%f\n", (float)( DiskLoad[ id ].s[ 2 ].delta / timeInterval ) ); } void print24DiskWIOInfo( const char* cmd ) { int id; sscanf( cmd + 9, "%d", &id ); output( "Disk %d Write\t0\t0\tKB/s\n", id ); } void print24DiskRBlk( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 9, "%d", &id ); /* a block is 512 bytes or 1/2 kBytes */ output( "%f\n", (float)( DiskLoad[ id ].s[ 3 ].delta / timeInterval * 2 ) ); } void print24DiskRBlkInfo( const char* cmd ) { int id; sscanf( cmd + 9, "%d", &id ); output( "Disk %d Read Data\t0\t0\tKB/s\n", id ); } void print24DiskWBlk( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + 9, "%d", &id ); /* a block is 512 bytes or 1/2 kBytes */ output( "%f\n", (float)( DiskLoad[ id ].s[ 4 ].delta / timeInterval * 2 ) ); } void print24DiskWBlkInfo( const char* cmd ) { int id; sscanf( cmd + 9, "%d", &id ); output( "Disk %d Write Data\t0\t0\tKB/s\n", id ); } void printPageIn( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", (float)( PageIn / timeInterval ) ); } void printPageInInfo( const char* cmd ) { (void)cmd; output( "Paged in Pages\t0\t0\t1/s\n" ); } void printPageOut( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", (float)( PageOut / timeInterval ) ); } void printPageOutInfo( const char* cmd ) { (void)cmd; output( "Paged out Pages\t0\t0\t1/s\n" ); } void printInterruptx( const char* cmd ) { int id; if ( StatDirty ) processStat(); sscanf( cmd + strlen( "cpu/interrupts/int" ), "%d", &id ); output( "%f\n", (float)( Intr[ id ] / timeInterval ) ); } void printInterruptxInfo( const char* cmd ) { int id; sscanf( cmd + strlen( "cpu/interrupt/int" ), "%d", &id ); output( "Interrupt %d\t0\t0\t1/s\n", id ); } void printCtxt( const char* cmd ) { (void)cmd; if ( StatDirty ) processStat(); output( "%f\n", (float)( Ctxt / timeInterval ) ); } void printCtxtInfo( const char* cmd ) { (void)cmd; output( "Context switches\t0\t0\t1/s\n" ); } void print24DiskIO( const char* cmd ) { int major, minor; char devname[DISKDEVNAMELEN]; char name[ 17 ]; DiskIOInfo* ptr; sscanf( cmd, "disk/%[^_]_(%d:%d)/%16s", devname, &major, &minor, name ); if ( StatDirty ) processStat(); ptr = DiskIO; while ( ptr && ( ptr->major != major || ptr->minor != minor ) ) ptr = ptr->next; if ( !ptr ) { print_error( "RECONFIGURE" ); output( "0\n" ); log_error( "Disk device disappeared" ); return; } if ( strcmp( name, "total" ) == 0 ) output( "%f\n", (float)( ptr->total.delta / timeInterval ) ); else if ( strcmp( name, "rio" ) == 0 ) output( "%f\n", (float)( ptr->rio.delta / timeInterval ) ); else if ( strcmp( name, "wio" ) == 0 ) output( "%f\n", (float)( ptr->wio.delta / timeInterval ) ); else if ( strcmp( name, "rblk" ) == 0 ) output( "%f\n", (float)( ptr->rblk.delta / ( timeInterval * 2 ) ) ); else if ( strcmp( name, "wblk" ) == 0 ) output( "%f\n", (float)( ptr->wblk.delta / ( timeInterval * 2 ) ) ); else { output( "0\n" ); log_error( "Unknown disk device property \'%s\'", name ); } } void print24DiskIOInfo( const char* cmd ) { int major, minor; char devname[DISKDEVNAMELEN]; char name[ 17 ]; DiskIOInfo* ptr = DiskIO; sscanf( cmd, "disk/%[^_]_(%d:%d)/%16s", devname, &major, &minor, name ); while ( ptr && ( ptr->major != major || ptr->minor != minor ) ) ptr = ptr->next; if ( !ptr ) { /* Disk device has disappeared. Print a dummy answer. */ output( "Dummy\t0\t0\t\n" ); return; } /* remove trailing '?' */ name[ strlen( name ) - 1 ] = '\0'; if ( strcmp( name, "total" ) == 0 ) output( "Total accesses device %s (%d:%d)\t0\t0\t1/s\n", devname, major, minor ); else if ( strcmp( name, "rio" ) == 0 ) output( "Read data device %s (%d:%d)\t0\t0\t1/s\n", devname, major, minor ); else if ( strcmp( name, "wio" ) == 0 ) output( "Write data device %s (%d:%d)\t0\t0\t1/s\n", devname, major, minor ); else if ( strcmp( name, "rblk" ) == 0 ) output( "Read accesses device %s (%d:%d)\t0\t0\tKB/s\n", devname, major, minor ); else if ( strcmp( name, "wblk" ) == 0 ) output( "Write accesses device %s (%d:%d)\t0\t0\tKB/s\n", devname, major, minor ); else { output( "Dummy\t0\t0\t\n" ); log_error( "Request for unknown device property \'%s\'", name ); } }