diskstats and slabinfo
This commit is contained in:
parent
87402486f7
commit
5c99a21b72
20
CodingStyle
20
CodingStyle
@ -3,6 +3,9 @@ If you change an existing file, follow the existing style.
|
|||||||
|
|
||||||
Hard tabs are OK, as long as you consider the tab stops to
|
Hard tabs are OK, as long as you consider the tab stops to
|
||||||
be every 8 characters. You can also use 2, 3, or 4 spaces.
|
be every 8 characters. You can also use 2, 3, or 4 spaces.
|
||||||
|
Tabs are kind of yucky, since cut-and-paste mangles them
|
||||||
|
sometimes and they make "diff -Naurd old new" output less
|
||||||
|
readable.
|
||||||
|
|
||||||
Spaces within a line don't matter much, and won't be
|
Spaces within a line don't matter much, and won't be
|
||||||
considered part of the style. Just make it readable:
|
considered part of the style. Just make it readable:
|
||||||
@ -44,6 +47,8 @@ fprintf(fd, "%d %d %d %d %d %d\n",
|
|||||||
sfssss + wwwwfwfw
|
sfssss + wwwwfwfw
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Keep these distinct: NULL, '\0', 0, 0.0
|
||||||
|
|
||||||
Command-line parsers need to be bomb-proof. It is not acceptable
|
Command-line parsers need to be bomb-proof. It is not acceptable
|
||||||
to crash due to a messed up command-line. For an option "-x" that
|
to crash due to a messed up command-line. For an option "-x" that
|
||||||
takes an argument, accept both "-x arg" and "-xarg". Remember to
|
takes an argument, accept both "-x arg" and "-xarg". Remember to
|
||||||
@ -56,15 +61,22 @@ non-ASCII characters to be printed. Assuming the console is
|
|||||||
not in UTF-8 mode, all of these are bad: "\b\e\f\n\r\t\v\x9b".
|
not in UTF-8 mode, all of these are bad: "\b\e\f\n\r\t\v\x9b".
|
||||||
(the "\x9b" is valid in UTF-8 mode, but equivalent to "\e["
|
(the "\x9b" is valid in UTF-8 mode, but equivalent to "\e["
|
||||||
when not in UTF-8 mode -- which gives control of terminal
|
when not in UTF-8 mode -- which gives control of terminal
|
||||||
settings)
|
settings) It's best if you consider user-supplied data to
|
||||||
|
be unsafe, since this makes for less work in case the code
|
||||||
|
ends up needing to run setuid. Termcap data is user-supplied.
|
||||||
|
Except for the above security issues, don't bother to check
|
||||||
|
for something you can't handle... like printf() failing.
|
||||||
|
It is expected that /dev exists and so on.
|
||||||
|
|
||||||
Remember that a read() may return early, with partial data
|
Remember that a read() may return early, with partial data
|
||||||
or with -1 and errno set to EINTR. You then must try again.
|
or with -1 and errno set to EINTR. You then must try again.
|
||||||
|
|
||||||
char: may be signed or unsigned by default
|
char: may be signed or unsigned by default
|
||||||
int: always 32-bit
|
int: always 32-bit
|
||||||
long long: always 64-bit
|
long long: always 64-bit
|
||||||
long: same size as a pointer, either 32-bit or 64-bit
|
pointer: either 32-bit or 64-bit
|
||||||
|
long: same size as a pointer
|
||||||
|
KLONG: same size as a pointer or long IN THE KERNEL
|
||||||
|
|
||||||
Functions used in just one file must be marked static.
|
Functions used in just one file must be marked static.
|
||||||
Use the "const" and "restrict" keywords wherever you can.
|
Use the "const" and "restrict" keywords wherever you can.
|
||||||
|
6
Makefile
6
Makefile
@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
VERSION := 3
|
VERSION := 3
|
||||||
SUBVERSION := 1
|
SUBVERSION := 1
|
||||||
MINORVERSION := 9
|
MINORVERSION := 10
|
||||||
TARVERSION := 3.1.9
|
TARVERSION := 3.1.10
|
||||||
LIBVERSION := 3.1.9
|
LIBVERSION := 3.1.10
|
||||||
|
|
||||||
############ vars
|
############ vars
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ global:
|
|||||||
Hertz; smp_num_cpus;
|
Hertz; smp_num_cpus;
|
||||||
sprint_uptime; uptime; user_from_uid; print_uptime; loadavg;
|
sprint_uptime; uptime; user_from_uid; print_uptime; loadavg;
|
||||||
pretty_print_signals; print_given_signals; unix_print_signals; signal_name_to_number; signal_number_to_name;
|
pretty_print_signals; print_given_signals; unix_print_signals; signal_name_to_number; signal_number_to_name;
|
||||||
meminfo; vminfo; getstat;
|
meminfo; vminfo; getstat; getdiskstat; getslabinfo;
|
||||||
kb_active; kb_inactive; kb_main_buffers; kb_main_cached;
|
kb_active; kb_inactive; kb_main_buffers; kb_main_cached;
|
||||||
kb_main_free; kb_main_total; kb_main_used; kb_swap_free;
|
kb_main_free; kb_main_total; kb_main_used; kb_swap_free;
|
||||||
kb_swap_total; kb_swap_used; kb_main_shared;
|
kb_swap_total; kb_swap_used; kb_main_shared;
|
||||||
|
116
proc/sysinfo.c
116
proc/sysinfo.c
@ -4,8 +4,10 @@
|
|||||||
// This file is placed under the conditions of the GNU Library
|
// This file is placed under the conditions of the GNU Library
|
||||||
// General Public License, version 2, or any later version.
|
// General Public License, version 2, or any later version.
|
||||||
// See file COPYING for information on distribution conditions.
|
// See file COPYING for information on distribution conditions.
|
||||||
|
//
|
||||||
/* File for parsing top-level /proc entities. */
|
// File for parsing top-level /proc entities. */
|
||||||
|
//
|
||||||
|
// June 2003, Fabian Frederick, disk and slab info
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -172,7 +174,9 @@ static void old_Hertz_hack(void){
|
|||||||
#define AT_CLKTCK 17 /* frequency of times() */
|
#define AT_CLKTCK 17 /* frequency of times() */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char** environ;
|
#define NOTE_NOT_FOUND 42
|
||||||
|
|
||||||
|
//extern char** environ;
|
||||||
|
|
||||||
/* for ELF executables, notes are pushed before environment and args */
|
/* for ELF executables, notes are pushed before environment and args */
|
||||||
static unsigned long find_elf_note(unsigned long findme){
|
static unsigned long find_elf_note(unsigned long findme){
|
||||||
@ -182,7 +186,7 @@ static unsigned long find_elf_note(unsigned long findme){
|
|||||||
if(ep[0]==findme) return ep[1];
|
if(ep[0]==findme) return ep[1];
|
||||||
ep+=2;
|
ep+=2;
|
||||||
}
|
}
|
||||||
return 42;
|
return NOTE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_libproc(void) __attribute__((constructor));
|
static void init_libproc(void) __attribute__((constructor));
|
||||||
@ -195,7 +199,7 @@ static void init_libproc(void){
|
|||||||
|
|
||||||
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
|
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
|
||||||
Hertz = find_elf_note(AT_CLKTCK);
|
Hertz = find_elf_note(AT_CLKTCK);
|
||||||
if(Hertz!=42) return;
|
if(Hertz!=NOTE_NOT_FOUND) return;
|
||||||
fprintf(stderr, "2.4 kernel w/o ELF notes? -- report to albert@users.sf.net\n");
|
fprintf(stderr, "2.4 kernel w/o ELF notes? -- report to albert@users.sf.net\n");
|
||||||
}
|
}
|
||||||
old_Hertz_hack();
|
old_Hertz_hack();
|
||||||
@ -651,3 +655,105 @@ nextline:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// based on Fabian Frederick's /proc/diskstats parser
|
||||||
|
|
||||||
|
static unsigned int getFileLines(const char* szFile){
|
||||||
|
char szBuffer[1024];
|
||||||
|
FILE *fdiskStat;
|
||||||
|
int lines=0;
|
||||||
|
if ((fdiskStat=fopen (szFile,"rb"))){
|
||||||
|
while (fgets(szBuffer, 1024, fdiskStat)){
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
fclose(fdiskStat);
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int getdiskstat(struct disk_stat **disks, struct partition_stat **partitions){
|
||||||
|
FILE* fd;
|
||||||
|
buff[BUFFSIZE-1] = 0;
|
||||||
|
int units,
|
||||||
|
i,
|
||||||
|
disk_type,
|
||||||
|
disk_num,
|
||||||
|
cDisk=0,
|
||||||
|
cPartition=0;
|
||||||
|
*disks = NULL;
|
||||||
|
*partitions = NULL;
|
||||||
|
units = getFileLines("/proc/diskstats");
|
||||||
|
fd = fopen("/proc/diskstats", "rb");
|
||||||
|
if(!fd) crash("/proc/diskstats");
|
||||||
|
|
||||||
|
for (i=0; i<units; i++){
|
||||||
|
if (!fgets(buff,BUFFSIZE-1,fd)){
|
||||||
|
fclose(fd);
|
||||||
|
crash("/proc/diskstats");
|
||||||
|
}
|
||||||
|
sscanf(buff, " %d %d", &disk_type, &disk_num);
|
||||||
|
if (disk_num == 0){
|
||||||
|
(*disks) = realloc(*disks, (cDisk+1)*sizeof(struct disk_stat));
|
||||||
|
sscanf(buff, " %d %*d %15s %u %u %llu %u %u %u %llu %u %u %u %u",
|
||||||
|
&(*disks)[cDisk].disk_type,
|
||||||
|
//&unused,
|
||||||
|
(*disks)[cDisk].disk_name,
|
||||||
|
&(*disks)[cDisk].reads,
|
||||||
|
&(*disks)[cDisk].merged_reads,
|
||||||
|
&(*disks)[cDisk].reads_sectors,
|
||||||
|
&(*disks)[cDisk].milli_reading,
|
||||||
|
&(*disks)[cDisk].writes,
|
||||||
|
&(*disks)[cDisk].merged_writes,
|
||||||
|
&(*disks)[cDisk].written_sectors,
|
||||||
|
&(*disks)[cDisk].milli_writing,
|
||||||
|
&(*disks)[cDisk].inprogress_IO,
|
||||||
|
&(*disks)[cDisk].milli_spent_IO,
|
||||||
|
&(*disks)[cDisk].weighted_milli_spent_IO
|
||||||
|
);
|
||||||
|
cDisk++;
|
||||||
|
}else{
|
||||||
|
(*partitions) = realloc(*partitions, (cPartition+1)*sizeof(struct partition_stat));
|
||||||
|
fflush(stdout);
|
||||||
|
sscanf(buff, " %d %d %15s %u %llu %u %u",
|
||||||
|
&(*partitions)[cPartition].disk_type,
|
||||||
|
&(*partitions)[cPartition].partition_num,
|
||||||
|
(*partitions)[cPartition].partition_name,
|
||||||
|
&(*partitions)[cPartition].reads,
|
||||||
|
&(*partitions)[cPartition].reads_sectors,
|
||||||
|
&(*partitions)[cPartition].writes,
|
||||||
|
&(*partitions)[cPartition].requested_writes
|
||||||
|
);
|
||||||
|
(*partitions)[cPartition++].parent_disk = &((*disks)[cDisk-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
return cDisk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// based on Fabian Frederick's /proc/slabinfo parser
|
||||||
|
|
||||||
|
unsigned int getslabinfo (struct slab_cache **slab){
|
||||||
|
FILE* fd;
|
||||||
|
int cSlab = 0;
|
||||||
|
buff[BUFFSIZE-1] = 0;
|
||||||
|
*slab = NULL;
|
||||||
|
fd = fopen("/proc/slabinfo", "rb");
|
||||||
|
if(!fd) crash("/proc/slabinfo");
|
||||||
|
while (fgets(buff,BUFFSIZE-1,fd)){
|
||||||
|
if(!memcmp("slabinfo - version:",buff,19)) continue; // skip header
|
||||||
|
if(*buff == '#') continue; // skip comments
|
||||||
|
(*slab) = realloc(*slab, (cSlab+1)*sizeof(struct slab_cache));
|
||||||
|
sscanf(buff, "%47s %u %u %u %u", // allow 47; max seen is 24
|
||||||
|
(*slab)[cSlab].name,
|
||||||
|
&(*slab)[cSlab].active_objs,
|
||||||
|
&(*slab)[cSlab].num_objs,
|
||||||
|
&(*slab)[cSlab].objsize,
|
||||||
|
&(*slab)[cSlab].objperslab
|
||||||
|
) ;
|
||||||
|
cSlab++;
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
return cSlab;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -88,5 +88,44 @@ extern unsigned long vm_allocstall;
|
|||||||
|
|
||||||
extern void vminfo(void);
|
extern void vminfo(void);
|
||||||
|
|
||||||
|
typedef struct disk_stat{
|
||||||
|
unsigned int disk_type;
|
||||||
|
char disk_name [16];
|
||||||
|
unsigned reads;
|
||||||
|
unsigned merged_reads;
|
||||||
|
unsigned long long reads_sectors;
|
||||||
|
unsigned milli_reading;
|
||||||
|
unsigned writes;
|
||||||
|
unsigned merged_writes;
|
||||||
|
unsigned long long written_sectors;
|
||||||
|
unsigned milli_writing;
|
||||||
|
unsigned inprogress_IO;
|
||||||
|
unsigned milli_spent_IO;
|
||||||
|
unsigned weighted_milli_spent_IO;
|
||||||
|
}disk_stat;
|
||||||
|
|
||||||
|
typedef struct partition_stat{
|
||||||
|
unsigned int disk_type;
|
||||||
|
unsigned int partition_num;
|
||||||
|
char partition_name [16];
|
||||||
|
struct disk_stat* parent_disk;
|
||||||
|
unsigned reads;
|
||||||
|
unsigned long long reads_sectors;
|
||||||
|
unsigned writes;
|
||||||
|
unsigned requested_writes;
|
||||||
|
}partition_stat;
|
||||||
|
|
||||||
|
extern unsigned int getdiskstat (struct disk_stat**,struct partition_stat**);
|
||||||
|
|
||||||
|
typedef struct slab_cache{
|
||||||
|
char name[48];
|
||||||
|
unsigned active_objs;
|
||||||
|
unsigned num_objs;
|
||||||
|
unsigned objsize;
|
||||||
|
unsigned objperslab;
|
||||||
|
}slab_cache;
|
||||||
|
|
||||||
|
extern unsigned int getslabinfo (struct slab_cache**);
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
#endif /* SYSINFO_H */
|
#endif /* SYSINFO_H */
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
Begin4
|
Begin4
|
||||||
Title: procps
|
Title: procps
|
||||||
Version: 3.1.9
|
Version: 3.1.10
|
||||||
Entered-date: 2003-03-27
|
Entered-date: 2003-06-08
|
||||||
Description: Linux system utilities
|
Description: Linux system utilities
|
||||||
Keywords: procps /proc libproc sysctl pmap ps uptime tload
|
Keywords: procps /proc libproc sysctl pmap ps uptime tload
|
||||||
free w top vmstat watch skill snice kill pgrep pkill
|
free w top vmstat watch skill snice kill pgrep pkill
|
||||||
Author: Albert Cahalan, Michael K. Johnson, Jim Warner, etc.
|
Author: Albert Cahalan, Michael K. Johnson, Jim Warner, etc.
|
||||||
Maintained-by: various <procps-feedback@lists.sf.net>
|
Maintained-by: various <procps-feedback@lists.sf.net>
|
||||||
Primary-site: http://procps.sf.net/
|
Primary-site: http://procps.sf.net/
|
||||||
239kB procps-3.1.9.tar.gz
|
239kB procps-3.1.10.tar.gz
|
||||||
Alternate-site: http://www.debian.org/Packages/unstable/base/procps.html
|
Alternate-site: http://www.debian.org/Packages/unstable/base/procps.html
|
||||||
239kB procps-3.1.9.tar.gz
|
239kB procps-3.1.10.tar.gz
|
||||||
Copying-policy: mixed
|
Copying-policy: mixed
|
||||||
End
|
End
|
||||||
|
@ -3,7 +3,7 @@ Summary: System and process monitoring utilities
|
|||||||
Name: procps
|
Name: procps
|
||||||
%define major_version 3
|
%define major_version 3
|
||||||
%define minor_version 1
|
%define minor_version 1
|
||||||
%define revision 9
|
%define revision 10
|
||||||
%define version %{major_version}.%{minor_version}.%{revision}
|
%define version %{major_version}.%{minor_version}.%{revision}
|
||||||
Version: %{version}
|
Version: %{version}
|
||||||
Release: 1
|
Release: 1
|
||||||
|
57
vmstat.8
57
vmstat.8
@ -13,11 +13,15 @@ vmstat \- Report virtual memory statistics
|
|||||||
.B vmstat
|
.B vmstat
|
||||||
.RB [ "\-f" ]
|
.RB [ "\-f" ]
|
||||||
.RB [ "\-s" ]
|
.RB [ "\-s" ]
|
||||||
|
.RB [ "\-m" ]
|
||||||
.br
|
.br
|
||||||
.B vmstat
|
.B vmstat
|
||||||
.RB [ "\-S unit"]
|
.RB [ "\-S unit"]
|
||||||
.br
|
.br
|
||||||
.B vmstat
|
.B vmstat
|
||||||
|
.RB [ "\-d"]
|
||||||
|
.br
|
||||||
|
.B vmstat
|
||||||
.RB [ "\-V" ]
|
.RB [ "\-V" ]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBvmstat\fP reports information about processes, memory, paging,
|
\fBvmstat\fP reports information about processes, memory, paging,
|
||||||
@ -36,6 +40,8 @@ equivalent to the total number of tasks created. Each process
|
|||||||
is represented by one or more tasks, depending on thread usage.
|
is represented by one or more tasks, depending on thread usage.
|
||||||
This display does not repeat.
|
This display does not repeat.
|
||||||
.PP
|
.PP
|
||||||
|
The \fB-m\fP displays slabinfo.
|
||||||
|
.PP
|
||||||
The \fB-n\fP switch causes the header to be displayed only once rather than periodically.
|
The \fB-n\fP switch causes the header to be displayed only once rather than periodically.
|
||||||
.PP
|
.PP
|
||||||
The \fB-s\fP switch displays a table of various event counters
|
The \fB-s\fP switch displays a table of various event counters
|
||||||
@ -49,11 +55,13 @@ only one report is printed with the average values since boot.
|
|||||||
is the number of updates. If no count is specified and delay is
|
is the number of updates. If no count is specified and delay is
|
||||||
defined, \fIcount\fP defaults to infinity.
|
defined, \fIcount\fP defaults to infinity.
|
||||||
.PP
|
.PP
|
||||||
|
The \fB-d\fP reports disk statistics (2.5.70 or above required)
|
||||||
|
.PP
|
||||||
The \fB-S\fP followed by k or K or m or M switches outputs between 1000, 1024, 1000000, or 1048576 bytes
|
The \fB-S\fP followed by k or K or m or M switches outputs between 1000, 1024, 1000000, or 1048576 bytes
|
||||||
.PP
|
.PP
|
||||||
The \fB-V\fP switch results in displaying version information.
|
The \fB-V\fP switch results in displaying version information.
|
||||||
.PP
|
.PP
|
||||||
.SH FIELD DESCRIPTIONS
|
.SH FIELD DESCRIPTION FOR VM MODE
|
||||||
.SS
|
.SS
|
||||||
.B "Procs"
|
.B "Procs"
|
||||||
.nf
|
.nf
|
||||||
@ -101,7 +109,47 @@ us: Time spent running non-kernel code. (user time, including nice time)
|
|||||||
sy: Time spent running kernel code. (system time)
|
sy: Time spent running kernel code. (system time)
|
||||||
id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
|
id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
|
||||||
wa: Time spent waiting for IO. Prior to Linux 2.5.41, shown as zero.
|
wa: Time spent waiting for IO. Prior to Linux 2.5.41, shown as zero.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.SH FIELD DESCRIPTION FOR DISK MODE
|
||||||
|
.SS
|
||||||
|
.B "Reads"
|
||||||
.nf
|
.nf
|
||||||
|
total: Total reads completed successfully
|
||||||
|
merged: grouped reads (resulting in one I/O)
|
||||||
|
sectors: Sectors read successfully
|
||||||
|
ms: milliseconds spent reading
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
.SS
|
||||||
|
.B "Writes"
|
||||||
|
.nf
|
||||||
|
total: Total writes completed successfully
|
||||||
|
merged: grouped writes (resulting in one I/O)
|
||||||
|
sectors: Sectors written successfully
|
||||||
|
ms: milliseconds spent writing
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
.SS
|
||||||
|
.B "IO"
|
||||||
|
.nf
|
||||||
|
cur: I/O in progress
|
||||||
|
s: seconds spent for I/O
|
||||||
|
.fi
|
||||||
|
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.SH FIELD DESCRIPTION FOR SLAB MODE
|
||||||
|
.nf
|
||||||
|
cache: Cache name
|
||||||
|
num: Number of currently active objects
|
||||||
|
total: Total number of available objects
|
||||||
|
size: Size of each object
|
||||||
|
pages: Number of pages with at least one active object
|
||||||
|
totpages: Total number of allocated pages
|
||||||
|
pslab: Number of pages per slab
|
||||||
|
.fi
|
||||||
|
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
.B "vmstat "
|
.B "vmstat "
|
||||||
does not require special permissions.
|
does not require special permissions.
|
||||||
@ -113,8 +161,9 @@ does not count itself as a running process.
|
|||||||
All linux blocks are currently 1024 bytes. Old kernels may report
|
All linux blocks are currently 1024 bytes. Old kernels may report
|
||||||
blocks as 512 bytes, 2048 bytes, or 4096 bytes.
|
blocks as 512 bytes, 2048 bytes, or 4096 bytes.
|
||||||
.PP
|
.PP
|
||||||
Since procps 3.1.9, vmstat lets you choose units (k, K, m, M)
|
Since procps 3.1.9, vmstat lets you choose units (k, K, m, M) default is K (1024 bytes) in the default mode
|
||||||
.PP
|
.PP
|
||||||
|
vmstat uses slabinfo 1.1 FIXME
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.ta
|
.ta
|
||||||
.nf
|
.nf
|
||||||
@ -128,5 +177,7 @@ iostat(1), sar(1), mpstat(1), ps(1), top(1), free(1)
|
|||||||
.PP
|
.PP
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Does not tabulate the block io per device or count the number of system calls.
|
Does not tabulate the block io per device or count the number of system calls.
|
||||||
.SH AUTHOR
|
.SH AUTHORS
|
||||||
|
.nf
|
||||||
Written by Henry Ware <al172@yfn.ysu.edu>.
|
Written by Henry Ware <al172@yfn.ysu.edu>.
|
||||||
|
Diskstat,slab mode and some improvements by Fabian Frederick <fabian.frederick@gmx.fr>
|
||||||
|
175
vmstat.c
175
vmstat.c
@ -3,6 +3,10 @@
|
|||||||
// 27/05/2003 (Fabian) : Add unit conversion + interface
|
// 27/05/2003 (Fabian) : Add unit conversion + interface
|
||||||
// Export proc/stat access to libproc
|
// Export proc/stat access to libproc
|
||||||
// Adapt vmstat helpfile
|
// Adapt vmstat helpfile
|
||||||
|
// 31/05/2003 (Fabian) : Add diskstat support (/libproc)
|
||||||
|
// June 2003 (Fabian) : -S <x> -s & -s -S <x> patch
|
||||||
|
// June 2003 (Fabian) : -Adding diskstat against 3.1.9, slabinfo
|
||||||
|
// -patching 'header' in disk & slab
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -19,7 +23,21 @@
|
|||||||
|
|
||||||
#include "proc/sysinfo.h"
|
#include "proc/sysinfo.h"
|
||||||
#include "proc/version.h"
|
#include "proc/version.h"
|
||||||
#include "vmstat.h"
|
|
||||||
|
static unsigned long dataUnit=1024;
|
||||||
|
static char szDataUnit [16];
|
||||||
|
#define UNIT_B 1
|
||||||
|
#define UNIT_k 1000
|
||||||
|
#define UNIT_K 1024
|
||||||
|
#define UNIT_m 1000000
|
||||||
|
#define UNIT_M 1048576
|
||||||
|
|
||||||
|
#define VMSTAT 0
|
||||||
|
#define DISKSTAT 0x00000001
|
||||||
|
#define VMSUMSTAT 0x00000002
|
||||||
|
#define SLABSTAT 0x00000004
|
||||||
|
|
||||||
|
static int statMode=VMSTAT;
|
||||||
|
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
@ -41,6 +59,8 @@ static void usage(void) {
|
|||||||
fprintf(stderr," -V prints version.\n");
|
fprintf(stderr," -V prints version.\n");
|
||||||
fprintf(stderr," -n causes the headers not to be reprinted regularly.\n");
|
fprintf(stderr," -n causes the headers not to be reprinted regularly.\n");
|
||||||
fprintf(stderr," -a print inactive/active page stats.\n");
|
fprintf(stderr," -a print inactive/active page stats.\n");
|
||||||
|
fprintf(stderr," -d prints disk statistics\n");
|
||||||
|
fprintf(stderr," -m prints slabinfo\n");
|
||||||
fprintf(stderr," -S unit size\n");
|
fprintf(stderr," -S unit size\n");
|
||||||
fprintf(stderr," delay is the delay between updates in seconds. \n");
|
fprintf(stderr," delay is the delay between updates in seconds. \n");
|
||||||
fprintf(stderr," unit size k:1000 K:1024 m:1000000 M:1048576 (default is K)\n");
|
fprintf(stderr," unit size k:1000 K:1024 m:1000000 M:1048576 (default is K)\n");
|
||||||
@ -132,10 +152,25 @@ static void new_header(void){
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
unsigned long unitConvert(unsigned int kbsize)
|
static void new_diskheader(void){
|
||||||
{
|
printf("disk ----------reads------------ -----------writes----------- -------IO-------\n");
|
||||||
|
|
||||||
|
printf("%3s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", " ", "total", "merged","sectors","ms","total","merged","sectors","ms","cur","s");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void new_slabheader(void){
|
||||||
|
printf("%-24s %6s %6s %6s %6s\n","Cache","Num", "Total", "Size", "Pages");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static unsigned long unitConvert(unsigned int size){
|
||||||
float cvSize;
|
float cvSize;
|
||||||
cvSize=(float)kbsize/dataUnit*1024;
|
cvSize=(float)size/dataUnit*((statMode==SLABSTAT)?1:1024);
|
||||||
return ((unsigned long) cvSize);
|
return ((unsigned long) cvSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +192,6 @@ static void new_format(void) {
|
|||||||
|
|
||||||
sleep_half=(sleep_time/2);
|
sleep_half=(sleep_time/2);
|
||||||
new_header();
|
new_header();
|
||||||
|
|
||||||
meminfo();
|
meminfo();
|
||||||
|
|
||||||
getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,cpu_iow,
|
getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,cpu_iow,
|
||||||
@ -240,6 +274,98 @@ static void new_format(void) {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void new_diskformat(void){
|
||||||
|
FILE *fDiskstat;
|
||||||
|
struct disk_stat *disks;
|
||||||
|
struct partition_stat *partitions;
|
||||||
|
unsigned long ndisks,i,j,k;
|
||||||
|
const char format[]="%-3s %6u %6u %6llu %6u %6u %6u %6llu %6u %6u %6u\n";
|
||||||
|
if ((fDiskstat=fopen("/proc/diskstats", "rb"))){
|
||||||
|
fclose(fDiskstat);
|
||||||
|
ndisks=getdiskstat(&disks,&partitions);
|
||||||
|
for(k=0; k<ndisks; k++){
|
||||||
|
if (moreheaders && ((k%height)==0)) new_diskheader();
|
||||||
|
printf(format,
|
||||||
|
disks[k].disk_name,disks[k].reads, disks[k].merged_reads,disks[k].reads_sectors, disks[k].milli_reading, disks[k].writes, disks[k].merged_writes, disks[k].written_sectors,disks[k].milli_writing, disks[k].inprogress_IO?disks[k].inprogress_IO/1000:0, disks[k].milli_spent_IO?disks[k].milli_spent_IO/1000:0/*, disks[i].weighted_milli_spent_IO/1000*/);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
free(disks);
|
||||||
|
free(partitions);
|
||||||
|
for(j=1; j<num_updates; j++){
|
||||||
|
sleep(sleep_time);
|
||||||
|
ndisks=getdiskstat(&disks,&partitions);
|
||||||
|
for(i=0; i<ndisks; i++,k++){
|
||||||
|
if (moreheaders && ((k%height)==0)) new_diskheader();
|
||||||
|
printf(format,
|
||||||
|
disks[i].disk_name,
|
||||||
|
disks[i].reads,
|
||||||
|
disks[i].merged_reads,
|
||||||
|
disks[i].reads_sectors,
|
||||||
|
disks[i].milli_reading,
|
||||||
|
disks[i].writes,
|
||||||
|
disks[i].merged_writes,
|
||||||
|
disks[i].written_sectors,
|
||||||
|
disks[i].milli_writing,
|
||||||
|
disks[i].inprogress_IO?disks[i].inprogress_IO/1000:0,
|
||||||
|
disks[i].milli_spent_IO?disks[i].milli_spent_IO/1000:0/*,
|
||||||
|
disks[i].weighted_milli_spent_IO/1000*/
|
||||||
|
);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
free(disks);
|
||||||
|
free(partitions);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
fprintf(stderr, "Your kernel doesn't support diskstat (2.5.70 or above required)");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void new_slabformat (void){
|
||||||
|
FILE *fSlab;
|
||||||
|
struct slab_cache *slabs;
|
||||||
|
unsigned long nSlab,i,j,k;
|
||||||
|
const char format[]="%-24s %6u %6u %6u %6u\n";
|
||||||
|
|
||||||
|
fSlab=fopen("/proc/slabinfo", "rb");
|
||||||
|
if(!fSlab){
|
||||||
|
fprintf(stderr, "Your kernel doesn't support slabinfo");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nSlab = getslabinfo(&slabs);
|
||||||
|
for(k=0; k<nSlab; k++){
|
||||||
|
if (moreheaders && ((k%height)==0)) new_slabheader();
|
||||||
|
printf(format,
|
||||||
|
slabs[k].name,
|
||||||
|
slabs[k].active_objs,
|
||||||
|
slabs[k].num_objs,
|
||||||
|
slabs[k].objsize,
|
||||||
|
slabs[k].objperslab
|
||||||
|
);
|
||||||
|
}
|
||||||
|
free(slabs);
|
||||||
|
for(j=1,k=1; j<num_updates; j++) {
|
||||||
|
sleep(sleep_time);
|
||||||
|
nSlab = getslabinfo(&slabs);
|
||||||
|
for(i=0; i<nSlab; i++,k++){
|
||||||
|
if (moreheaders && ((k%height)==0)) new_slabheader();
|
||||||
|
printf(format,
|
||||||
|
slabs[i].name,
|
||||||
|
slabs[i].active_objs,
|
||||||
|
slabs[i].num_objs,
|
||||||
|
slabs[i].objsize,
|
||||||
|
slabs[i].objperslab
|
||||||
|
);
|
||||||
|
}
|
||||||
|
free(slabs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void sum_format(void) {
|
static void sum_format(void) {
|
||||||
unsigned int running, blocked, btime, processes;
|
unsigned int running, blocked, btime, processes;
|
||||||
jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow;
|
jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow;
|
||||||
@ -278,6 +404,9 @@ static void sum_format(void) {
|
|||||||
printf("%13u boot time\n", btime);
|
printf("%13u boot time\n", btime);
|
||||||
printf("%13u forks\n", processes);
|
printf("%13u forks\n", processes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void fork_format(void) {
|
static void fork_format(void) {
|
||||||
unsigned int running, blocked, btime, processes;
|
unsigned int running, blocked, btime, processes;
|
||||||
jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow;
|
jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow;
|
||||||
@ -293,6 +422,7 @@ static void fork_format(void) {
|
|||||||
printf("%13u forks\n", processes);
|
printf("%13u forks\n", processes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static int winhi(void) {
|
static int winhi(void) {
|
||||||
struct winsize win;
|
struct winsize win;
|
||||||
@ -304,16 +434,20 @@ static int winhi(void) {
|
|||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
argc=0; /* redefined as number of integer arguments */
|
argc=0; /* redefined as number of integer arguments */
|
||||||
for (argv++;*argv;argv++) {
|
for (argv++;*argv;argv++) {
|
||||||
if ('-' ==(**argv)) {
|
if ('-' ==(**argv)) {
|
||||||
switch (*(++(*argv))) {
|
switch (*(++(*argv))) {
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
display_version();
|
display_version();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
case 'd':
|
||||||
|
statMode |= DISKSTAT;
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
/* active/inactive mode */
|
/* active/inactive mode */
|
||||||
a_option=1;
|
a_option=1;
|
||||||
@ -322,6 +456,9 @@ int main(int argc, char *argv[]) {
|
|||||||
// FIXME: check for conflicting args
|
// FIXME: check for conflicting args
|
||||||
fork_format();
|
fork_format();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
case 'm':
|
||||||
|
statMode |= SLABSTAT;
|
||||||
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
/* print only one header */
|
/* print only one header */
|
||||||
moreheaders=FALSE;
|
moreheaders=FALSE;
|
||||||
@ -341,16 +478,14 @@ int main(int argc, char *argv[]) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
// FIXME: check for conflicting args
|
statMode |= VMSUMSTAT;
|
||||||
sum_format();
|
break;
|
||||||
exit(0);
|
|
||||||
default:
|
default:
|
||||||
/* no other aguments defined yet. */
|
/* no other aguments defined yet. */
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
} else {
|
}else{
|
||||||
argc++;
|
argc++;
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 1:
|
case 1:
|
||||||
@ -364,17 +499,25 @@ int main(int argc, char *argv[]) {
|
|||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
} /* switch */
|
} /* switch */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (moreheaders) {
|
if (moreheaders) {
|
||||||
int tmp=winhi()-3;
|
int tmp=winhi()-3;
|
||||||
height=((tmp>0)?tmp:22);
|
height=((tmp>0)?tmp:22);
|
||||||
}
|
}
|
||||||
|
|
||||||
setlinebuf(stdout);
|
setlinebuf(stdout);
|
||||||
|
switch(statMode){
|
||||||
new_format();
|
case(VMSTAT): new_format();
|
||||||
|
break;
|
||||||
|
case(VMSUMSTAT):sum_format();
|
||||||
|
break;
|
||||||
|
case(DISKSTAT): new_diskformat();
|
||||||
|
break;
|
||||||
|
case(SLABSTAT): new_slabformat();
|
||||||
|
break;
|
||||||
|
default: usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
vmstat.h
7
vmstat.h
@ -19,9 +19,16 @@
|
|||||||
#define _IVMstat
|
#define _IVMstat
|
||||||
unsigned long dataUnit=1024;
|
unsigned long dataUnit=1024;
|
||||||
char szDataUnit [16];
|
char szDataUnit [16];
|
||||||
|
#define UNIT_B 1
|
||||||
#define UNIT_k 1000
|
#define UNIT_k 1000
|
||||||
#define UNIT_K 1024
|
#define UNIT_K 1024
|
||||||
#define UNIT_m 1000000
|
#define UNIT_m 1000000
|
||||||
#define UNIT_M 1048576
|
#define UNIT_M 1048576
|
||||||
|
|
||||||
|
#define VMSTAT 1
|
||||||
|
#define DISKSTAT 2
|
||||||
|
#define VMSUMSTAT 3
|
||||||
|
#define SLABSTAT 4
|
||||||
|
|
||||||
|
int statMode=VMSTAT;
|
||||||
#endif /* _IVMstat */
|
#endif /* _IVMstat */
|
||||||
|
Loading…
Reference in New Issue
Block a user