⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iostat.c

📁 linux下查看系统工具原码,如IOSTAT等
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * iostat: report CPU and I/O statistics * (C) 1998-2006 by Sebastien GODARD (sysstat <at> wanadoo.fr) * *************************************************************************** * 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 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                   * *************************************************************************** */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>#include <errno.h>#include <time.h>#include <ctype.h>#include <dirent.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/utsname.h>#include <sys/param.h>	/* for HZ */#include "iostat.h"#include "common.h"#include "ioconf.h"#ifdef USE_NLS#include <locale.h>#include <libintl.h>#define _(string) gettext(string)#else#define _(string) (string)#endifstruct comm_stats  comm_stats[2];struct io_stats *st_iodev[2];struct io_hdr_stats *st_hdr_iodev;struct io_dlist *st_dev_list;/* Nb of devices and partitions found */int iodev_nr = 0;/* Nb of devices entered on the command line */int dlist_idx = 0;long interval = 0;unsigned char timestamp[64];/* * Nb of processors on the machine. * A value of 1 means two procs... */int cpu_nr = -1;/* *************************************************************************** * Print usage and exit *************************************************************************** */void usage(char *progname){   fprintf(stderr, _("Usage: %s [ options... ] [ <interval> [ <count> ] ]\n"		   "Options are:\n"		   "[ -c | -d ] [ -k | -m ] [ -t ] [ -V ] [ -x ]\n"		   "[ <device> [ ... ] | ALL ] [ -p [ <device> | ALL ] ]\n"),	   progname);   exit(1);}/* *************************************************************************** * SIGALRM signal handler *************************************************************************** */void alarm_handler(int sig){   signal(SIGALRM, alarm_handler);   alarm(interval);}/* *************************************************************************** * Initialize stats common structures *************************************************************************** */void init_stats(void){   memset(&comm_stats[0], 0, COMM_STATS_SIZE);   memset(&comm_stats[1], 0, COMM_STATS_SIZE);}/* *************************************************************************** * Set every disk_io entry to inactive state *************************************************************************** */void set_entries_inactive(int iodev_nr){   int i;   struct io_hdr_stats *shi = st_hdr_iodev;   for (i = 0; i < iodev_nr; i++, shi++)      shi->active = FALSE;}/* *************************************************************************** * Set structures's state to free for inactive entries *************************************************************************** */void free_inactive_entries(int iodev_nr){   int i;   struct io_hdr_stats *shi = st_hdr_iodev;   for (i = 0; i < iodev_nr; i++, shi++) {      if (!shi->active)	 shi->used = FALSE;   }}/* *************************************************************************** * Allocate and init I/O devices structures *************************************************************************** */void salloc_device(int iodev_nr){   int i;   for (i = 0; i < 2; i++) {      if ((st_iodev[i] = (struct io_stats *) malloc(IO_STATS_SIZE * iodev_nr)) == NULL) {	 perror("malloc");	 exit(4);      }      memset(st_iodev[i], 0, IO_STATS_SIZE * iodev_nr);   }   if ((st_hdr_iodev = (struct io_hdr_stats *) malloc(IO_HDR_STATS_SIZE * iodev_nr)) == NULL) {      perror("malloc");      exit(4);   }   memset(st_hdr_iodev, 0, IO_HDR_STATS_SIZE * iodev_nr);}/* *************************************************************************** * Allocate structures for devices entered on the command line *************************************************************************** */void salloc_dev_list(int list_len){   if ((st_dev_list = (struct io_dlist *) malloc(IO_DLIST_SIZE * list_len)) == NULL) {      perror("malloc");      exit(4);   }   memset(st_dev_list, 0, IO_DLIST_SIZE * list_len);}/* *************************************************************************** * Look for the device in the device list and store it if necessary. * Returns the position of the device in the list. *************************************************************************** */int update_dev_list(int *dlist_idx, char *device_name){   int i;   struct io_dlist *sdli = st_dev_list;   for (i = 0; i < *dlist_idx; i++, sdli++) {      if (!strcmp(sdli->dev_name, device_name))	 break;   }   if (i == *dlist_idx) {      /* Device not found: store it */      (*dlist_idx)++;      strncpy(sdli->dev_name, device_name, MAX_NAME_LEN - 1);   }   return i;}/* *************************************************************************** * Allocate and init structures, according to system state *************************************************************************** */void io_sys_init(int *flags){   int i;   /* Init stat common counters */   init_stats();   /* How many processors on this machine ? */   cpu_nr = get_cpu_nr(~0);   /* Get number of block devices and partitions in /proc/diskstats */   if ((iodev_nr = get_diskstats_dev_nr(CNT_PART, CNT_ALL_DEV)) > 0) {      *flags |= I_F_HAS_DISKSTATS;      iodev_nr += NR_DEV_PREALLOC;   }   if (!HAS_DISKSTATS(*flags) ||       (DISPLAY_PARTITIONS(*flags) && !DISPLAY_PART_ALL(*flags))) {      /*       * If /proc/diskstats exists but we also want stats for the partitions       * of a particular device, stats will have to be found in /sys. So we       * need to know if /sys is mounted or not, and set *flags accordingly.       */      /* Get number of block devices (and partitions) in sysfs */      if ((iodev_nr = get_sysfs_dev_nr(DISPLAY_PARTITIONS(*flags))) > 0) {	 *flags |= I_F_HAS_SYSFS;	 iodev_nr += NR_DEV_PREALLOC;      }      /*       * Get number of block devices and partitions in /proc/partitions,       * those with statistics...       */      else if ((iodev_nr = get_ppartitions_dev_nr(CNT_PART)) > 0) {	 *flags |= I_F_HAS_PPARTITIONS;	 iodev_nr += NR_DEV_PREALLOC;      }      /* Get number of "disk_io:" entries in /proc/stat */      else if ((iodev_nr = get_disk_io_nr()) > 0) {	 *flags |= I_F_PLAIN_KERNEL24;	 iodev_nr += NR_DISK_PREALLOC;      }      else {	 /* Assume we have an old kernel: stats for 4 disks are in /proc/stat */	 iodev_nr = 4;	 *flags |= I_F_OLD_KERNEL;      }   }   /* Allocate structures for number of disks found */   salloc_device(iodev_nr);   if (HAS_OLD_KERNEL(*flags)) {      struct io_hdr_stats *shi = st_hdr_iodev;      /*       * If we have an old kernel with the stats for the first four disks       * in /proc/stat, then set the devices names to hdisk[0..3].       */      for (i = 0; i < 4; i++, shi++) {	 shi->used = TRUE;	 sprintf(shi->name, "%s%d", K_HDISK, i);      }   }}/* *************************************************************************** * Save stats for current device or partition *************************************************************************** */void save_dev_stats(char *dev_name, int curr, struct io_stats *sdev){   int i;   struct io_hdr_stats *st_hdr_iodev_i;   struct io_stats *st_iodev_i;   /* Look for device in data table */   for (i = 0; i < iodev_nr; i++) {      st_hdr_iodev_i = st_hdr_iodev + i;      if (!strcmp(st_hdr_iodev_i->name, dev_name)) {	 break;      }   }	   if (i == iodev_nr) {      /*       * This is a new device: look for an unused entry to store it.       * Thus we are able to handle dynamically registered devices.       */      for (i = 0; i < iodev_nr; i++) {	 st_hdr_iodev_i = st_hdr_iodev + i;	 if (!st_hdr_iodev_i->used) {	    /* Unused entry found... */	    st_hdr_iodev_i->used = TRUE;	/* Indicate it is now used */	    strcpy(st_hdr_iodev_i->name, dev_name);	    st_iodev_i = st_iodev[!curr] + i;	    memset(st_iodev_i, 0, IO_STATS_SIZE);	    break;	 }      }   }   if (i < iodev_nr) {      st_hdr_iodev_i = st_hdr_iodev + i;      st_hdr_iodev_i->active = TRUE;      st_iodev_i = st_iodev[curr] + i;      *st_iodev_i = *sdev;   }   /* else it was a new device but there was no free structure to store it */}/* *************************************************************************** * Read stats from /proc/stat file... * Useful at least for CPU utilization. * May be useful to get disk stats if /sys not available. *************************************************************************** */void read_proc_stat(int curr, int flags){   FILE *fp;   char line[8192];   int pos, i;   unsigned long v_tmp[4];   unsigned int v_major, v_index;   struct io_stats *st_iodev_tmp[4];   unsigned long long cc_idle, cc_iowait, cc_steal;   unsigned long long cc_user, cc_nice, cc_system, cc_hardirq, cc_softirq;   /*    * Prepare pointers on the 4 disk structures in case we have a    * /proc/stat file with "disk_rblk", etc. entries.    */   for (i = 0; i < 4; i++)      st_iodev_tmp[i] = st_iodev[curr] + i;   if ((fp = fopen(STAT, "r")) == NULL) {      perror("fopen");      exit(2);   }   while (fgets(line, 8192, fp) != NULL) {      if (!strncmp(line, "cpu ", 4)) {	 /*	  * Read the number of jiffies spent in the different modes,	  * and compute system uptime in jiffies (1/100ths of a second	  * if HZ=100).	  * Some fields are only presnt in 2.6 kernels.	  */	 comm_stats[curr].cpu_iowait = 0;	/* For pre 2.6 kernels */	 comm_stats[curr].cpu_steal = 0;	 cc_hardirq = cc_softirq = 0;	 /* CPU counters became unsigned long long with kernel 2.6.5 */	 sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu",	        &(comm_stats[curr].cpu_user), &(comm_stats[curr].cpu_nice),		&(comm_stats[curr].cpu_system), &(comm_stats[curr].cpu_idle),		&(comm_stats[curr].cpu_iowait), &cc_hardirq, &cc_softirq,		&(comm_stats[curr].cpu_steal));	 /*	  * Time spent in system mode also includes time spent servicing	  * hard interrupts and softirqs.	  */	 comm_stats[curr].cpu_system += cc_hardirq + cc_softirq;		 /*	  * Compute system uptime in jiffies.	  * Uptime is multiplied by the number of processors.	  */	 comm_stats[curr].uptime = comm_stats[curr].cpu_user   +	                           comm_stats[curr].cpu_nice +	                           comm_stats[curr].cpu_system +	                           comm_stats[curr].cpu_idle +	                           comm_stats[curr].cpu_iowait +	    			   comm_stats[curr].cpu_steal;      }      else if ((!strncmp(line, "cpu0", 4)) && cpu_nr) {	 /*	  * Read CPU line for proc#0 (if available).	  * Useful to compute uptime reduced to one processor on SMP machines,	  * with fewer risks to get an overflow...	  */	 cc_iowait = cc_hardirq = cc_softirq = cc_steal = 0;	 sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu",		&cc_user, &cc_nice, &cc_system, &cc_idle, &cc_iowait,		&cc_hardirq, &cc_softirq, &cc_steal);	 comm_stats[curr].uptime0 = cc_user + cc_nice + cc_system +	    			    cc_idle + cc_iowait +	    			    cc_hardirq + cc_softirq + cc_steal;      }      else if (DISPLAY_EXTENDED(flags) || HAS_DISKSTATS(flags) ||	       HAS_PPARTITIONS(flags) || HAS_SYSFS(flags))	 /*	  * When displaying extended statistics, or if /proc/diskstats or	  * /proc/partitions exists, or /sys is mounted,	  * we just need to get CPU info from /proc/stat.	  */	 continue;      else if (!strncmp(line, "disk_rblk ", 10)) {	 /*	  * Read the number of blocks read from disk.	  * A block is of indeterminate size.	  * The size may vary depending on the device type.	  */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -