2 KSysGuard, the KDE System Guard
4 Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of version 2 of the GNU General Public
8 License as published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * stat.c is used to read from /proc/[pid]/stat
23 #include <sys/types.h>
34 #include "ksysguardd.h"
39 /* A CPU can be loaded with user processes, reniced processes and
40 * system processes. Unused processing time is called idle load.
41 * These variable store the percentage of each load type. */
48 /* To calculate the loads we need to remember the tick values for each
50 unsigned long userTicks
;
51 unsigned long niceTicks
;
52 unsigned long sysTicks
;
53 unsigned long idleTicks
;
54 unsigned long waitTicks
;
63 /* 5 types of samples are taken:
64 total, rio, wio, rBlk, wBlk */
65 DiskLoadSample s
[ 5 ];
68 typedef struct DiskIOInfo
{
79 struct DiskIOInfo
* next
;
82 #define STATBUFSIZE (32 * 1024)
83 #define DISKDEVNAMELEN 16
85 static char StatBuf
[ STATBUFSIZE
];
86 static char VmStatBuf
[ STATBUFSIZE
];
89 /* We have observed deviations of up to 5% in the accuracy of the timer
90 * interrupts. So we try to measure the interrupt interval and use this
91 * value to calculate timing dependant values. */
92 static float timeInterval
= 0;
93 static struct timeval lastSampling
;
94 static struct timeval currSampling
;
95 static struct SensorModul
* StatSM
;
97 static CPULoadInfo CPULoad
;
98 static CPULoadInfo
* SMPLoad
= 0;
99 static unsigned CPUCount
= 0;
100 static DiskLoadInfo
* DiskLoad
= 0;
101 static unsigned DiskCount
= 0;
102 static DiskIOInfo
* DiskIO
= 0;
103 static unsigned long PageIn
= 0;
104 static unsigned long OldPageIn
= 0;
105 static unsigned long PageOut
= 0;
106 static unsigned long OldPageOut
= 0;
107 static unsigned long Ctxt
= 0;
108 static unsigned long OldCtxt
= 0;
109 static unsigned int NumOfInts
= 0;
110 static unsigned long* OldIntr
= 0;
111 static unsigned long* Intr
= 0;
113 static int initStatDisk( char* tag
, char* buf
, const char* label
, const char* shortLabel
,
114 int idx
, cmdExecutor ex
, cmdExecutor iq
);
115 static void updateCPULoad( const char* line
, CPULoadInfo
* load
);
116 static int process24Disk( char* tag
, char* buf
, const char* label
, int idx
);
117 static void process24Stat( void );
118 static int process24DiskIO( const char* buf
);
119 static void cleanup24DiskList( void );
121 static int initStatDisk( char* tag
, char* buf
, const char* label
,
122 const char* shortLabel
, int idx
, cmdExecutor ex
, cmdExecutor iq
)
124 char sensorName
[ 128 ];
126 gettimeofday( &lastSampling
, 0 );
128 if ( strcmp( label
, tag
) == 0 ) {
130 buf
= buf
+ strlen( label
) + 1;
132 for ( i
= 0; i
< DiskCount
; ++i
) {
133 sscanf( buf
, "%lu", &DiskLoad
[ i
].s
[ idx
].old
);
134 while ( *buf
&& isblank( *buf
++ ) );
135 while ( *buf
&& isdigit( *buf
++ ) );
136 sprintf( sensorName
, "disk/disk%d/%s", i
, shortLabel
);
137 registerMonitor( sensorName
, "float", ex
, iq
, StatSM
);
149 * Parses the total cpu status line from /proc/stat
151 static void updateCPULoad( const char* line
, CPULoadInfo
* load
) {
152 unsigned long currUserTicks
, currSysTicks
, currNiceTicks
;
153 unsigned long currIdleTicks
, currWaitTicks
, totalTicks
;
155 sscanf( line
, "%*s %lu %lu %lu %lu %lu", &currUserTicks
, &currNiceTicks
,
156 &currSysTicks
, &currIdleTicks
, &currWaitTicks
);
158 totalTicks
= ( currUserTicks
- load
->userTicks
) +
159 ( currSysTicks
- load
->sysTicks
) +
160 ( currNiceTicks
- load
->niceTicks
) +
161 ( currIdleTicks
- load
->idleTicks
) +
162 ( currWaitTicks
- load
->waitTicks
);
164 if ( totalTicks
> 10 ) {
165 load
->userLoad
= ( 100.0 * ( currUserTicks
- load
->userTicks
) ) / totalTicks
;
166 load
->sysLoad
= ( 100.0 * ( currSysTicks
- load
->sysTicks
) ) / totalTicks
;
167 load
->niceLoad
= ( 100.0 * ( currNiceTicks
- load
->niceTicks
) ) / totalTicks
;
168 load
->idleLoad
= ( 100.0 * ( currIdleTicks
- load
->idleTicks
) ) / totalTicks
;
169 load
->waitLoad
= ( 100.0 * ( currWaitTicks
- load
->waitTicks
) ) / totalTicks
;
172 load
->userLoad
= load
->sysLoad
= load
->niceLoad
= load
->idleLoad
= load
->waitLoad
= 0.0;
174 load
->userTicks
= currUserTicks
;
175 load
->sysTicks
= currSysTicks
;
176 load
->niceTicks
= currNiceTicks
;
177 load
->idleTicks
= currIdleTicks
;
178 load
->waitTicks
= currWaitTicks
;
181 static int process24Disk( char* tag
, char* buf
, const char* label
, int idx
) {
182 if ( strcmp( label
, tag
) == 0 ) {
185 buf
= buf
+ strlen( label
) + 1;
187 for ( i
= 0; i
< DiskCount
; ++i
) {
188 sscanf( buf
, "%lu", &val
);
189 while ( *buf
&& isblank( *buf
++ ) );
190 while ( *buf
&& isdigit( *buf
++ ) );
191 DiskLoad
[ i
].s
[ idx
].delta
= val
- DiskLoad
[ i
].s
[ idx
].old
;
192 DiskLoad
[ i
].s
[ idx
].old
= val
;
201 static int process24DiskIO( const char* buf
) {
202 /* Process disk_io lines as provided by 2.4.x kernels.
203 * disk_io: (2,0):(3,3,6,0,0) (3,0):(1413012,511622,12155382,901390,26486215) */
205 unsigned long total
, rblk
, rio
, wblk
, wio
;
206 DiskIOInfo
* ptr
= DiskIO
;
207 DiskIOInfo
* last
= 0;
208 char sensorName
[ 128 ];
211 p
= buf
+ strlen( "disk_io: " );
213 if ( sscanf( p
, "(%d,%d):(%lu,%lu,%lu,%lu,%lu)", &major
, &minor
,
214 &total
, &rio
, &rblk
, &wio
, &wblk
) != 7 )
220 if ( ptr
->major
== major
&& ptr
->minor
== minor
) {
221 /* The IO device has already been registered. */
222 ptr
->total
.delta
= total
- ptr
->total
.old
;
223 ptr
->total
.old
= total
;
224 ptr
->rio
.delta
= rio
- ptr
->rio
.old
;
226 ptr
->wio
.delta
= wio
- ptr
->wio
.old
;
228 ptr
->rblk
.delta
= rblk
- ptr
->rblk
.old
;
229 ptr
->rblk
.old
= rblk
;
230 ptr
->wblk
.delta
= wblk
- ptr
->wblk
.old
;
231 ptr
->wblk
.old
= wblk
;
241 /* The IO device has not been registered yet. We need to add it. */
242 ptr
= (DiskIOInfo
*)malloc( sizeof( DiskIOInfo
) );
246 /* 2.6 gives us a nice device name. On 2.4 we get nothing */
247 ptr
->devname
= (char *)malloc( DISKDEVNAMELEN
);
248 memset( ptr
->devname
, 0, DISKDEVNAMELEN
);
250 ptr
->total
.delta
= 0;
251 ptr
->total
.old
= total
;
257 ptr
->rblk
.old
= rblk
;
259 ptr
->wblk
.old
= wblk
;
263 /* Append new entry at end of list. */
267 /* List is empty, so we insert the fist element into the list. */
271 sprintf( sensorName
, "disk/%s_(%d:%d)24/total", ptr
->devname
, major
, minor
);
272 registerMonitor( sensorName
, "float", print24DiskIO
, print24DiskIOInfo
, StatSM
);
273 sprintf( sensorName
, "disk/%s_(%d:%d)24/rio", ptr
->devname
, major
, minor
);
274 registerMonitor( sensorName
, "float", print24DiskIO
, print24DiskIOInfo
, StatSM
);
275 sprintf( sensorName
, "disk/%s_(%d:%d)24/wio", ptr
->devname
, major
, minor
);
276 registerMonitor( sensorName
, "float", print24DiskIO
, print24DiskIOInfo
, StatSM
);
277 sprintf( sensorName
, "disk/%s_(%d:%d)24/rblk", ptr
->devname
, major
, minor
);
278 registerMonitor( sensorName
, "float", print24DiskIO
, print24DiskIOInfo
, StatSM
);
279 sprintf( sensorName
, "disk/%s_(%d:%d)24/wblk", ptr
->devname
, major
, minor
);
280 registerMonitor( sensorName
, "float", print24DiskIO
, print24DiskIOInfo
, StatSM
);
283 /* Move p after the second ')'. We can safely assume that
284 * those two ')' exist. */
285 p
= strchr( p
, ')' ) + 1;
286 p
= strchr( p
, ')' ) + 1;
288 p
= strchr( p
, '(' );
294 static void cleanup24DiskList( void ) {
295 DiskIOInfo
* ptr
= DiskIO
;
296 DiskIOInfo
* last
= 0;
299 if ( ptr
->alive
== 0 ) {
301 char sensorName
[ 128 ];
303 /* Disk device has disappeared. We have to remove it from
304 * the list and unregister the monitors. */
305 sprintf( sensorName
, "disk/%s_(%d:%d)24/total", ptr
->devname
, ptr
->major
, ptr
->minor
);
306 removeMonitor( sensorName
);
307 sprintf( sensorName
, "disk/%s_(%d:%d)24/rio", ptr
->devname
, ptr
->major
, ptr
->minor
);
308 removeMonitor( sensorName
);
309 sprintf( sensorName
, "disk/%s_(%d:%d)24/wio", ptr
->devname
, ptr
->major
, ptr
->minor
);
310 removeMonitor( sensorName
);
311 sprintf( sensorName
, "disk/%s_(%d:%d)24/rblk", ptr
->devname
, ptr
->major
, ptr
->minor
);
312 removeMonitor( sensorName
);
313 sprintf( sensorName
, "disk/%s_(%d:%d)24/wblk", ptr
->devname
, ptr
->major
, ptr
->minor
);
314 removeMonitor( sensorName
);
316 last
->next
= ptr
->next
;
336 static void process24Stat( void ) {
338 char tagFormat
[ 16 ];
341 char* statBufP
= StatBuf
;
342 char* vmstatBufP
= VmStatBuf
;
344 sprintf( format
, "%%%d[^\n]\n", (int)sizeof( buf
) - 1 );
345 sprintf( tagFormat
, "%%%ds", (int)sizeof( tag
) - 1 );
347 while ( sscanf( statBufP
, format
, buf
) == 1 ) {
348 buf
[ sizeof( buf
) - 1 ] = '\0';
349 statBufP
+= strlen( buf
) + 1; /* move statBufP to next line */
350 sscanf( buf
, tagFormat
, tag
);
352 if ( strcmp( "cpu", tag
) == 0 ) {
354 updateCPULoad( buf
, &CPULoad
);
356 else if ( strncmp( "cpu", tag
, 3 ) == 0 ) {
357 /* Load for each SMP CPU */
359 sscanf( tag
+ 3, "%d", &id
);
360 updateCPULoad( buf
, &SMPLoad
[ id
] );
362 else if ( process24Disk( tag
, buf
, "disk", 0 ) ) {
364 else if ( process24Disk( tag
, buf
, "disk_rio", 1 ) ) {
366 else if ( process24Disk( tag
, buf
, "disk_wio", 2 ) ) {
368 else if ( process24Disk( tag
, buf
, "disk_rblk", 3 ) ) {
370 else if ( process24Disk( tag
, buf
, "disk_wblk", 4 ) ) {
372 else if ( strcmp( "disk_io:", tag
) == 0 ) {
373 process24DiskIO( buf
);
375 else if ( strcmp( "page", tag
) == 0 ) {
376 unsigned long v1
, v2
;
377 sscanf( buf
+ 5, "%lu %lu", &v1
, &v2
);
378 PageIn
= v1
- OldPageIn
;
380 PageOut
= v2
- OldPageOut
;
383 else if ( strcmp( "intr", tag
) == 0 ) {
387 for ( i
= 0; i
< NumOfInts
; i
++ ) {
390 sscanf( p
, "%lu", &val
);
391 Intr
[ i
] = val
- OldIntr
[ i
];
393 while ( *p
&& *p
!= ' ' )
395 while ( *p
&& *p
== ' ' )
398 } else if ( strcmp( "ctxt", tag
) == 0 ) {
401 sscanf( buf
+ 5, "%lu", &val
);
402 Ctxt
= val
- OldCtxt
;
407 /* Read Linux 2.5.x /proc/vmstat */
408 while ( sscanf( vmstatBufP
, format
, buf
) == 1 ) {
409 buf
[ sizeof( buf
) - 1 ] = '\0';
410 vmstatBufP
+= strlen( buf
) + 1; /* move vmstatBufP to next line */
411 sscanf( buf
, tagFormat
, tag
);
413 if ( strcmp( "pgpgin", tag
) == 0 ) {
415 sscanf( buf
+ 7, "%lu", &v1
);
416 PageIn
= v1
- OldPageIn
;
419 else if ( strcmp( "pgpgout", tag
) == 0 ) {
421 sscanf( buf
+ 7, "%lu", &v1
);
422 PageOut
= v1
- OldPageOut
;
427 /* save exact time inverval between this and the last read of /proc/stat */
428 timeInterval
= currSampling
.tv_sec
- lastSampling
.tv_sec
+
429 ( currSampling
.tv_usec
- lastSampling
.tv_usec
) / 1000000.0;
430 lastSampling
= currSampling
;
438 ================================ public part =================================
441 void initStat( struct SensorModul
* sm
) {
442 /* The CPU load is calculated from the values in /proc/stat. The cpu
443 * entry contains 7 counters. These counters count the number of ticks
444 * the system has spend on user processes, system processes, nice
445 * processes, idle and IO-wait time, hard and soft interrupts.
447 * SMP systems will have cpu1 to cpuN lines right after the cpu info. The
448 * format is identical to cpu and reports the information for each cpu.
449 * Linux kernels <= 2.0 do not provide this information!
451 * The /proc/stat file looks like this:
453 * cpu <user> <nice> <system> <idling> <waiting> <hardinterrupt> <softinterrupt>
455 * disk_rio 6889 0 0 0
457 * disk_rblk 13775 0 0 0
458 * disk_wblk 1816 0 0 0
461 * intr 50444 38672 2557 0 0 0 0 2 0 2 0 0 3 1429 1 7778 0
466 * Linux kernel >= 2.4.0 have one or more disk_io: lines instead of
469 * Linux kernel >= 2.6.x(?) have disk I/O stats in /proc/diskstats
470 * and no disk relevant lines are found in /proc/stat
474 char tagFormat
[ 16 ];
477 char* statBufP
= StatBuf
;
478 char* vmstatBufP
= VmStatBuf
;
484 sprintf( format
, "%%%d[^\n]\n", (int)sizeof( buf
) - 1 );
485 sprintf( tagFormat
, "%%%ds", (int)sizeof( tag
) - 1 );
487 while ( sscanf( statBufP
, format
, buf
) == 1 ) {
488 buf
[ sizeof( buf
) - 1 ] = '\0';
489 statBufP
+= strlen( buf
) + 1; /* move statBufP to next line */
490 sscanf( buf
, tagFormat
, tag
);
492 if ( strcmp( "cpu", tag
) == 0 ) {
494 registerMonitor( "cpu/system/user", "float", printCPUUser
, printCPUUserInfo
, StatSM
);
495 registerMonitor( "cpu/system/nice", "float", printCPUNice
, printCPUNiceInfo
, StatSM
);
496 registerMonitor( "cpu/system/sys", "float", printCPUSys
, printCPUSysInfo
, StatSM
);
497 registerMonitor( "cpu/system/TotalLoad", "float", printCPUTotalLoad
, printCPUTotalLoadInfo
, StatSM
);
498 registerMonitor( "cpu/system/idle", "float", printCPUIdle
, printCPUIdleInfo
, StatSM
);
499 registerMonitor( "cpu/system/wait", "float", printCPUWait
, printCPUWaitInfo
, StatSM
);
501 /* Monitor names changed from kde3 => kde4. Remain compatible with legacy requests when possible. */
502 registerLegacyMonitor( "cpu/user", "float", printCPUUser
, printCPUUserInfo
, StatSM
);
503 registerLegacyMonitor( "cpu/nice", "float", printCPUNice
, printCPUNiceInfo
, StatSM
);
504 registerLegacyMonitor( "cpu/sys", "float", printCPUSys
, printCPUSysInfo
, StatSM
);
505 registerLegacyMonitor( "cpu/TotalLoad", "float", printCPUTotalLoad
, printCPUTotalLoadInfo
, StatSM
);
506 registerLegacyMonitor( "cpu/idle", "float", printCPUIdle
, printCPUIdleInfo
, StatSM
);
507 registerLegacyMonitor( "cpu/wait", "float", printCPUWait
, printCPUWaitInfo
, StatSM
);
509 else if ( strncmp( "cpu", tag
, 3 ) == 0 ) {
511 /* Load for each SMP CPU */
514 sscanf( tag
+ 3, "%d", &id
);
516 sprintf( cmdName
, "cpu/cpu%d/user", id
);
517 registerMonitor( cmdName
, "float", printCPUxUser
, printCPUxUserInfo
, StatSM
);
518 sprintf( cmdName
, "cpu/cpu%d/nice", id
);
519 registerMonitor( cmdName
, "float", printCPUxNice
, printCPUxNiceInfo
, StatSM
);
520 sprintf( cmdName
, "cpu/cpu%d/sys", id
);
521 registerMonitor( cmdName
, "float", printCPUxSys
, printCPUxSysInfo
, StatSM
);
522 sprintf( cmdName
, "cpu/cpu%d/TotalLoad", id
);
523 registerMonitor( cmdName
, "float", printCPUxTotalLoad
, printCPUxTotalLoadInfo
, StatSM
);
524 sprintf( cmdName
, "cpu/cpu%d/idle", id
);
525 registerMonitor( cmdName
, "float", printCPUxIdle
, printCPUxIdleInfo
, StatSM
);
526 sprintf( cmdName
, "cpu/cpu%d/wait", id
);
527 registerMonitor( cmdName
, "float", printCPUxWait
, printCPUxWaitInfo
, StatSM
);
529 else if ( strcmp( "disk", tag
) == 0 ) {
533 /* Count the number of registered disks */
534 for ( DiskCount
= 0; *b
&& sscanf( b
, "%lu", &val
) == 1; DiskCount
++ ) {
535 while ( *b
&& isblank( *b
++ ) );
536 while ( *b
&& isdigit( *b
++ ) );
540 DiskLoad
= (DiskLoadInfo
*)malloc( sizeof( DiskLoadInfo
) * DiskCount
);
542 initStatDisk( tag
, buf
, "disk", "disk", 0, print24DiskTotal
, print24DiskTotalInfo
);
544 else if ( initStatDisk( tag
, buf
, "disk_rio", "rio", 1, print24DiskRIO
, print24DiskRIOInfo
) );
545 else if ( initStatDisk( tag
, buf
, "disk_wio", "wio", 2, print24DiskWIO
, print24DiskWIOInfo
) );
546 else if ( initStatDisk( tag
, buf
, "disk_rblk", "rblk", 3, print24DiskRBlk
, print24DiskRBlkInfo
) );
547 else if ( initStatDisk( tag
, buf
, "disk_wblk", "wblk", 4, print24DiskWBlk
, print24DiskWBlkInfo
) );
548 else if ( strcmp( "disk_io:", tag
) == 0 )
549 process24DiskIO( buf
);
550 else if ( strcmp( "page", tag
) == 0 ) {
551 sscanf( buf
+ 5, "%lu %lu", &OldPageIn
, &OldPageOut
);
552 registerMonitor( "cpu/pageIn", "float", printPageIn
, printPageInInfo
, StatSM
);
553 registerMonitor( "cpu/pageOut", "float", printPageOut
, printPageOutInfo
, StatSM
);
555 else if ( strcmp( "intr", tag
) == 0 ) {
560 /* Count the number of listed values in the intr line. */
566 /* It looks like anything above 24 is always 0. So let's just
567 * ignore this for the time being. */
568 if ( NumOfInts
> 25 )
570 OldIntr
= (unsigned long*)malloc( NumOfInts
* sizeof( unsigned long ) );
571 Intr
= (unsigned long*)malloc( NumOfInts
* sizeof( unsigned long ) );
574 for ( i
= 0; p
&& i
< NumOfInts
; i
++ ) {
575 sscanf( p
, "%lu", &OldIntr
[ i
] );
576 while ( *p
&& *p
!= ' ' )
578 while ( *p
&& *p
== ' ' )
580 sprintf( cmdName
, "cpu/interrupts/int%02d", i
);
581 registerMonitor( cmdName
, "float", printInterruptx
, printInterruptxInfo
, StatSM
);
584 else if ( strcmp( "ctxt", tag
) == 0 ) {
585 sscanf( buf
+ 5, "%lu", &OldCtxt
);
586 registerMonitor( "cpu/context", "float", printCtxt
, printCtxtInfo
, StatSM
);
590 while ( sscanf( vmstatBufP
, format
, buf
) == 1 ) {
591 buf
[ sizeof( buf
) - 1 ] = '\0';
592 vmstatBufP
+= strlen( buf
) + 1; /* move vmstatBufP to next line */
593 sscanf( buf
, tagFormat
, tag
);
595 if ( strcmp( "pgpgin", tag
) == 0 ) {
596 sscanf( buf
+ 7, "%lu", &OldPageIn
);
597 registerMonitor( "cpu/pageIn", "float", printPageIn
, printPageInInfo
, StatSM
);
599 else if ( strcmp( "pgpgout", tag
) == 0 ) {
600 sscanf( buf
+ 7, "%lu", &OldPageOut
);
601 registerMonitor( "cpu/pageOut", "float", printPageOut
, printPageOutInfo
, StatSM
);
606 SMPLoad
= (CPULoadInfo
*)malloc( sizeof( CPULoadInfo
) * CPUCount
);
608 /* Call process24Stat to eliminate initial peek values. */
612 void exitStat( void ) {
625 removeMonitor("cpu/system/user");
626 removeMonitor("cpu/system/nice");
627 removeMonitor("cpu/system/sys");
628 removeMonitor("cpu/system/idle");
630 /* Todo: Dynamically registered monitors (per cpu, per disk) are not removed yet) */
632 /* These were registered as legacy monitors */
633 removeMonitor("cpu/user");
634 removeMonitor("cpu/nice");
635 removeMonitor("cpu/sys");
636 removeMonitor("cpu/idle");
639 int updateStat( void ) {
643 gettimeofday( &currSampling
, 0 );
647 if ( ( fd
= open( "/proc/stat", O_RDONLY
) ) < 0 ) {
648 print_error( "Cannot open file \'/proc/stat\'!\n"
649 "The kernel needs to be compiled with support\n"
650 "for /proc file system enabled!\n" );
654 n
= read( fd
, StatBuf
, STATBUFSIZE
- 1 );
655 if ( n
== STATBUFSIZE
- 1 || n
<= 0) {
656 log_error( "Internal buffer too small to read \'/proc/stat\'" );
665 VmStatBuf
[ 0 ] = '\0';
666 if ( ( fd
= open( "/proc/vmstat", O_RDONLY
) ) < 0 )
667 return 0; /* failure is okay, only exists for Linux >= 2.5.x */
669 n
= read( fd
, VmStatBuf
, STATBUFSIZE
- 1 );
670 if ( n
== STATBUFSIZE
- 1 || n
<= 0 ) {
671 log_error( "Internal buffer too small to read \'/proc/vmstat\'" );
677 VmStatBuf
[ n
] = '\0';
682 void printCPUUser( const char* cmd
) {
688 fprintf( CurrentClient
, "%f\n", CPULoad
.userLoad
);
691 void printCPUUserInfo( const char* cmd
) {
694 fprintf( CurrentClient
, "CPU User Load\t0\t100\t%%\n" );
697 void printCPUNice( const char* cmd
) {
703 fprintf( CurrentClient
, "%f\n", CPULoad
.niceLoad
);
706 void printCPUNiceInfo( const char* cmd
) {
709 fprintf( CurrentClient
, "CPU Nice Load\t0\t100\t%%\n" );
712 void printCPUSys( const char* cmd
) {
718 fprintf( CurrentClient
, "%f\n", CPULoad
.sysLoad
);
721 void printCPUSysInfo( const char* cmd
) {
724 fprintf( CurrentClient
, "CPU System Load\t0\t100\t%%\n" );
727 void printCPUTotalLoad( const char* cmd
) {
733 fprintf( CurrentClient
, "%f\n", CPULoad
.userLoad
+ CPULoad
.sysLoad
+ CPULoad
.niceLoad
+ CPULoad
.waitLoad
);
736 void printCPUTotalLoadInfo( const char* cmd
) {
739 fprintf( CurrentClient
, "CPU Total Load\t0\t100\t%%\n" );
742 void printCPUIdle( const char* cmd
) {
748 fprintf( CurrentClient
, "%f\n", CPULoad
.idleLoad
);
751 void printCPUIdleInfo( const char* cmd
) {
754 fprintf( CurrentClient
, "CPU Idle Load\t0\t100\t%%\n" );
757 void printCPUWait( const char* cmd
)
764 fprintf( CurrentClient
, "%f\n", CPULoad
.waitLoad
);
767 void printCPUWaitInfo( const char* cmd
)
770 fprintf( CurrentClient
, "CPU Wait Load\t0\t100\t%%\n" );
773 void printCPUxUser( const char* cmd
) {
779 sscanf( cmd
+ 7, "%d", &id
);
780 fprintf( CurrentClient
, "%f\n", SMPLoad
[ id
].userLoad
);
783 void printCPUxUserInfo( const char* cmd
) {
786 sscanf( cmd
+ 7, "%d", &id
);
787 fprintf( CurrentClient
, "CPU%d User Load\t0\t100\t%%\n", id
);
790 void printCPUxNice( const char* cmd
) {
796 sscanf( cmd
+ 7, "%d", &id
);
797 fprintf( CurrentClient
, "%f\n", SMPLoad
[ id
].niceLoad
);
800 void printCPUxNiceInfo( const char* cmd
) {
803 sscanf( cmd
+ 7, "%d", &id
);
804 fprintf( CurrentClient
, "CPU%d Nice Load\t0\t100\t%%\n", id
);
807 void printCPUxSys( const char* cmd
) {
813 sscanf( cmd
+ 7, "%d", &id
);
814 fprintf( CurrentClient
, "%f\n", SMPLoad
[ id
].sysLoad
);
817 void printCPUxSysInfo( const char* cmd
) {
820 sscanf( cmd
+ 7, "%d", &id
);
821 fprintf( CurrentClient
, "CPU%d System Load\t0\t100\t%%\n", id
);
824 void printCPUxTotalLoad( const char* cmd
) {
830 sscanf( cmd
+ 7, "%d", &id
);
831 fprintf( CurrentClient
, "%f\n", SMPLoad
[ id
].userLoad
+ SMPLoad
[ id
].sysLoad
+ SMPLoad
[ id
].niceLoad
+ SMPLoad
[ id
].waitLoad
);
834 void printCPUxTotalLoadInfo( const char* cmd
) {
837 sscanf( cmd
+ 7, "%d", &id
);
838 fprintf( CurrentClient
, "CPU%d Total Load\t0\t100\t%%\n", id
);
841 void printCPUxIdle( const char* cmd
) {
847 sscanf( cmd
+ 7, "%d", &id
);
848 fprintf( CurrentClient
, "%f\n", SMPLoad
[ id
].idleLoad
);
851 void printCPUxIdleInfo( const char* cmd
) {
854 sscanf( cmd
+ 7, "%d", &id
);
855 fprintf( CurrentClient
, "CPU%d Idle Load\t0\t100\t%%\n", id
);
858 void printCPUxWait( const char* cmd
)
865 sscanf( cmd
+ 7, "%d", &id
);
866 fprintf( CurrentClient
, "%f\n", SMPLoad
[ id
].waitLoad
);
869 void printCPUxWaitInfo( const char* cmd
)
873 sscanf( cmd
+ 7, "%d", &id
);
874 fprintf( CurrentClient
, "CPU%d Wait Load\t0\t100\t%%\n", id
);
877 void print24DiskTotal( const char* cmd
) {
883 sscanf( cmd
+ 9, "%d", &id
);
884 fprintf( CurrentClient
, "%f\n", (float)( DiskLoad
[ id
].s
[ 0 ].delta
888 void print24DiskTotalInfo( const char* cmd
) {
891 sscanf( cmd
+ 9, "%d", &id
);
892 fprintf( CurrentClient
, "Disk%d Total Load\t0\t0\tkBytes/s\n", id
);
895 void print24DiskRIO( const char* cmd
) {
901 sscanf( cmd
+ 9, "%d", &id
);
902 fprintf( CurrentClient
, "%f\n", (float)( DiskLoad
[ id
].s
[ 1 ].delta
906 void print24DiskRIOInfo( const char* cmd
) {
909 sscanf( cmd
+ 9, "%d", &id
);
910 fprintf( CurrentClient
, "Disk%d Read\t0\t0\tkBytes/s\n", id
);
913 void print24DiskWIO( const char* cmd
) {
919 sscanf( cmd
+ 9, "%d", &id
);
920 fprintf( CurrentClient
, "%f\n", (float)( DiskLoad
[ id
].s
[ 2 ].delta
924 void print24DiskWIOInfo( const char* cmd
) {
927 sscanf( cmd
+ 9, "%d", &id
);
928 fprintf( CurrentClient
, "Disk%d Write\t0\t0\tkBytes/s\n", id
);
931 void print24DiskRBlk( const char* cmd
) {
937 sscanf( cmd
+ 9, "%d", &id
);
938 /* a block is 512 bytes or 1/2 kBytes */
939 fprintf( CurrentClient
, "%f\n", (float)( DiskLoad
[ id
].s
[ 3 ].delta
/ timeInterval
* 2 ) );
942 void print24DiskRBlkInfo( const char* cmd
) {
945 sscanf( cmd
+ 9, "%d", &id
);
946 fprintf( CurrentClient
, "Disk%d Read Data\t0\t0\tkBytes/s\n", id
);
949 void print24DiskWBlk( const char* cmd
) {
955 sscanf( cmd
+ 9, "%d", &id
);
956 /* a block is 512 bytes or 1/2 kBytes */
957 fprintf( CurrentClient
, "%f\n", (float)( DiskLoad
[ id
].s
[ 4 ].delta
/ timeInterval
* 2 ) );
960 void print24DiskWBlkInfo( const char* cmd
) {
963 sscanf( cmd
+ 9, "%d", &id
);
964 fprintf( CurrentClient
, "Disk%d Write Data\t0\t0\tkBytes/s\n", id
);
967 void printPageIn( const char* cmd
) {
973 fprintf( CurrentClient
, "%f\n", (float)( PageIn
/ timeInterval
) );
976 void printPageInInfo( const char* cmd
) {
979 fprintf( CurrentClient
, "Paged in Pages\t0\t0\t1/s\n" );
982 void printPageOut( const char* cmd
) {
988 fprintf( CurrentClient
, "%f\n", (float)( PageOut
/ timeInterval
) );
991 void printPageOutInfo( const char* cmd
) {
994 fprintf( CurrentClient
, "Paged out Pages\t0\t0\t1/s\n" );
997 void printInterruptx( const char* cmd
) {
1003 sscanf( cmd
+ strlen( "cpu/interrupts/int" ), "%d", &id
);
1004 fprintf( CurrentClient
, "%f\n", (float)( Intr
[ id
] / timeInterval
) );
1007 void printInterruptxInfo( const char* cmd
) {
1010 sscanf( cmd
+ strlen( "cpu/interrupt/int" ), "%d", &id
);
1011 fprintf( CurrentClient
, "Interrupt %d\t0\t0\t1/s\n", id
);
1014 void printCtxt( const char* cmd
) {
1020 fprintf( CurrentClient
, "%f\n", (float)( Ctxt
/ timeInterval
) );
1023 void printCtxtInfo( const char* cmd
) {
1026 fprintf( CurrentClient
, "Context switches\t0\t0\t1/s\n" );
1029 void print24DiskIO( const char* cmd
) {
1031 char devname
[DISKDEVNAMELEN
];
1035 sscanf( cmd
, "disk/%[^_]_(%d:%d)/%16s", devname
, &major
, &minor
, name
);
1041 while ( ptr
&& ( ptr
->major
!= major
|| ptr
->minor
!= minor
) )
1045 print_error( "RECONFIGURE" );
1046 fprintf( CurrentClient
, "0\n" );
1048 log_error( "Disk device disappeared" );
1052 if ( strcmp( name
, "total" ) == 0 )
1053 fprintf( CurrentClient
, "%f\n", (float)( ptr
->total
.delta
/ timeInterval
) );
1054 else if ( strcmp( name
, "rio" ) == 0 )
1055 fprintf( CurrentClient
, "%f\n", (float)( ptr
->rio
.delta
/ timeInterval
) );
1056 else if ( strcmp( name
, "wio" ) == 0 )
1057 fprintf( CurrentClient
, "%f\n", (float)( ptr
->wio
.delta
/ timeInterval
) );
1058 else if ( strcmp( name
, "rblk" ) == 0 )
1059 fprintf( CurrentClient
, "%f\n", (float)( ptr
->rblk
.delta
/ ( timeInterval
* 2 ) ) );
1060 else if ( strcmp( name
, "wblk" ) == 0 )
1061 fprintf( CurrentClient
, "%f\n", (float)( ptr
->wblk
.delta
/ ( timeInterval
* 2 ) ) );
1063 fprintf( CurrentClient
, "0\n" );
1064 log_error( "Unknown disk device property \'%s\'", name
);
1068 void print24DiskIOInfo( const char* cmd
) {
1070 char devname
[DISKDEVNAMELEN
];
1072 DiskIOInfo
* ptr
= DiskIO
;
1074 sscanf( cmd
, "disk/%[^_]_(%d:%d)/%16s", devname
, &major
, &minor
, name
);
1076 while ( ptr
&& ( ptr
->major
!= major
|| ptr
->minor
!= minor
) )
1080 /* Disk device has disappeared. Print a dummy answer. */
1081 fprintf( CurrentClient
, "Dummy\t0\t0\t\n" );
1085 /* remove trailing '?' */
1086 name
[ strlen( name
) - 1 ] = '\0';
1088 if ( strcmp( name
, "total" ) == 0 )
1089 fprintf( CurrentClient
, "Total accesses device %s (%d:%d)\t0\t0\t1/s\n",
1090 devname
, major
, minor
);
1091 else if ( strcmp( name
, "rio" ) == 0 )
1092 fprintf( CurrentClient
, "Read data device %s (%d:%d)\t0\t0\t1/s\n",
1093 devname
, major
, minor
);
1094 else if ( strcmp( name
, "wio" ) == 0 )
1095 fprintf( CurrentClient
, "Write data device %s (%d:%d)\t0\t0\t1/s\n",
1096 devname
, major
, minor
);
1097 else if ( strcmp( name
, "rblk" ) == 0 )
1098 fprintf( CurrentClient
, "Read accesses device %s (%d:%d)\t0\t0\tkBytes/s\n",
1099 devname
, major
, minor
);
1100 else if ( strcmp( name
, "wblk" ) == 0 )
1101 fprintf( CurrentClient
, "Write accesses device %s (%d:%d)\t0\t0\tkBytes/s\n",
1102 devname
, major
, minor
);
1104 fprintf( CurrentClient
, "Dummy\t0\t0\t\n" );
1105 log_error( "Request for unknown device property \'%s\'", name
);