PDA

View Full Version : I/O Detection program


Smotang
09-26-2006, 08:53 AM
// SE Toolkit program - http://www.setoolkit.com
//
// psio.se - a "ps -ef" style tool that prints I/O. Solaris, SE Toolkit.
//
// This program could assist finding a process that is causing the most I/O.
// The I/O reported is the total of all types: disk I/O, network I/O,
// stream I/O, etc..
//
// This is an SE Toolkit version of the perl "psio" program. The perl version
// reports disk I/O only, and has many different switches and modes of
// operation. Future versions of this SE Toolkit program are unlikely to
// have any extra features (for more features, see "pea.se").
//
// 12-Mar-2004, ver 0.70
//
//
// USAGE: se psio.se [-h] | [interval [count]]
//
// se psio.se # "ps -ef" style output, 1 second sample
// se psio.se 10 # print a 10 second sample
// se psio.se 10 5 # print 5 x 10 second samples
//
// se psio.se 30 | sort -n +3 # sort by I/O, 30 sec sample
//
// se psio.se 5 12 | grep [f]sflush # examine "fsflush" for 1 min
//
//
// FIELDS:
// IOSIZE Size of I/O (Kbytes)
//
// SEE ALSO: se -DWIDE pea.se # SE Toolkit
// psio # http://www.brendangregg.com/psio.html
//
// COPYRIGHT: Copyright (c) 2004 Brendan Gregg.
//
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// (http://www.gnu.org/copyleft/gpl.html)
//
// Author: Brendan Gregg [Sydney, Australia]
//
// 12-Mar-2004 Brendan Gregg Created this.


#define BLK 8192
#include <stdio.se>
#include <stdlib.se>
#include <unistd.se>
#include <string.se>
#include <dirent.se>
#include <time.se>
#include <fcntl.se>
#include <proc.se>
#include <process_class.se>
#include <pwd.se>


main(int argc, string argv[2]) {
//
// Variable declaration
//
psinfo_t p; /* raw proc info */
proc_class_t pp; /* advanced proc info */
passwd_t user; /* passwd structure, used for uid->name */
ulong user_ptr; /* passwd pointer */
tm_t time_tm; /* time structure, time conversions */
ulong time_ulong; /* temporary time variable */
char time[16]; /* TIME field */
char stime[16]; /* STIME field */
string username; /* username field */
double io_bytes; /* I/O bytes */
double io_kb; /* I/O Kbytes */
int i = 0; /* main loop counter */
int secs; /* interval seconds */
int loop; /* loop limit */

//
// Process command line args
//
if ((argc > 1) && (argv[1] == "-h" || argv[1] == "--help")) {
usage(argv[0]);
}
switch(argc) {
case 3:
secs = atoi(argv[1]);
loop = atoi(argv[2]);
break;
case 2:
secs = atoi(argv[1]);
loop = 1;
break;
default:
secs = 0;
loop = 1;
break;
}

//
// Prime initial I/O values
//
refresh$(pp);
pp.action$ = PROC_ACTION_NEXT_INDEX;
for (;;) {
refresh$(pp);
if (pp.index$ == -1) { break; }
// we read the following to reset the counters
io_bytes = pp.inblocks*BLK + pp.outblocks*BLK + pp.charios;
}


//
// Main loop
//
for (;;) {

// print header
if (i > 0) { printf("\n"); }
printf(" UID PID PPID IOSIZE STIME TTY TIME CMD\n");

// sleep while I/O occurs
sleep(secs);

//
// Print process listing
//
for (;;) {
refresh$(pp);
if (pp.index$ == -1) { break; }

// we need this structure to fetch the start time and tty
p = get_proc(pp.pid$);

// calculate start time
time_ulong = p.pr_start.tv_sec;
time_tm = localtime(&time_ulong);
strftime(stime, sizeof(stime), "%b %d", time_tm);

// calculate CPU time
time_ulong = pp.total_user + pp.total_system;
time_tm = gmtime(&time_ulong);
strftime(time, sizeof(time), "%M:%S", time_tm);

// get username
user_ptr = getpwuid(pp.uid);
user = *((passwd_t *) user_ptr);
username = user.pw_name;

// calculate I/O by bytes
io_bytes = pp.inblocks*BLK + pp.outblocks*BLK + pp.charios;
io_kb = io_bytes / 1024;

printf("%8s %5d %5d %7.1f %8s %-6s %6s %s\n",
username, pp.pid$, pp.ppid, io_kb, stime,
dev_to_tty(p.pr_ttydev), time, pp.args);
}

if (++i == loop) { break; }
}
}



//
// Subroutines
//

// usage - print usage and exit.
//
usage (string cmd)
{
printf("USAGE: se %s [-h] | [interval [count]]\n",cmd);
printf(" eg, se %s # print a 1 second sample\n",cmd);
printf(" eg, se %s 10 # print a 10 second sample\n",cmd);
printf(" eg, se %s 10 5 # print 5 x 10 second samples\n",cmd);
exit(1);
}




Very helpful piece of Code.