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

📄 sa_common.c

📁 linux下查看系统工具原码,如IOSTAT等
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sar and sadf common routines. * (C) 1999-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 <time.h>#include <errno.h>#include <unistd.h>	/* For STDOUT_FILENO, among others */#include <dirent.h>#include <fcntl.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/param.h>	/* for HZ */#include "sa.h"#include "common.h"#include "ioconf.h"#ifdef USE_NLS#include <locale.h>#include <libintl.h>#define _(string) gettext(string)#else#define _(string) (string)#endif/* *************************************************************************** * Init a bitmap (CPU, IRQ, etc.) *************************************************************************** */void init_bitmap(unsigned char bitmap[], unsigned char value, unsigned int nr){   register int i;   for (i = 0; i <= nr >> 3; i++)      bitmap[i] = value;}/* *************************************************************************** * Init stats structures *************************************************************************** */void init_stats(struct file_stats file_stats[],		unsigned int interrupts[][NR_IRQS]){   int i;   for (i = 0; i < DIM; i++) {      memset(&file_stats[i], 0, FILE_STATS_SIZE);      memset(interrupts[i], 0, STATS_ONE_IRQ_SIZE);   }}/* *************************************************************************** * Allocate stats_one_cpu structures * (only on SMP machines) *************************************************************************** */void salloc_cpu_array(struct stats_one_cpu *st_cpu[], unsigned int nr_cpu){   int i;   for (i = 0; i < DIM; i++)      SREALLOC(st_cpu[i], struct stats_one_cpu, STATS_ONE_CPU_SIZE * nr_cpu);}/* *************************************************************************** * Allocate stats_serial structures *************************************************************************** */void salloc_serial_array(struct stats_serial *st_serial[], int nr_serial){   int i;   for (i = 0; i < DIM; i++)      SREALLOC(st_serial[i], struct stats_serial, STATS_SERIAL_SIZE * nr_serial);}/* *************************************************************************** * Allocate stats_irq_cpu structures *************************************************************************** */void salloc_irqcpu_array(struct stats_irq_cpu *st_irq_cpu[],			 unsigned int nr_cpus, unsigned int nr_irqcpu){   int i;   for (i = 0; i < DIM; i++)      SREALLOC(st_irq_cpu[i], struct stats_irq_cpu,	       STATS_IRQ_CPU_SIZE * nr_cpus * nr_irqcpu);}/* *************************************************************************** * Allocate stats_net_dev structures *************************************************************************** */void salloc_net_dev_array(struct stats_net_dev *st_net_dev[],			  unsigned int nr_iface){   int i;   for (i = 0; i < DIM; i++)      SREALLOC(st_net_dev[i], struct stats_net_dev, STATS_NET_DEV_SIZE * nr_iface);}/* *************************************************************************** * Allocate disk_stats structures *************************************************************************** */void salloc_disk_array(struct disk_stats *st_disk[], int nr_disk){   int i;   for (i = 0; i < DIM; i++)      SREALLOC(st_disk[i], struct disk_stats, DISK_STATS_SIZE * nr_disk);}/* *************************************************************************** * Get device real name if possible. * Warning: This routine may return a bad name on 2.4 kernels where * disk activities are read from /proc/stat. *************************************************************************** */char *get_devname(unsigned int major, unsigned int minor, int pretty){   static char buf[32];   char *name;   snprintf(buf, 32, "dev%d-%d", major, minor);   if (!pretty)      return (buf);   if ((name = ioc_name(major, minor)) == NULL)      return (buf);   return (name);}/* *************************************************************************** * Check if we are close enough to desired interval ****************************************************************************/int next_slice(unsigned long long uptime_ref, unsigned long long uptime,	       struct file_hdr *file_hdr, int reset, long interval){   unsigned long file_interval, entry;   static unsigned long long last_uptime = 0;   int min, max, pt1, pt2;   double f;   if (!last_uptime || reset)      last_uptime = uptime_ref;   /* Interval cannot be greater than 0xffffffff here */   f = (((double) ((uptime - last_uptime) & 0xffffffff)) /	(file_hdr->sa_proc + 1)) / HZ;   file_interval = (unsigned long) f;   if ((f * 10) - (file_interval * 10) >= 5)      file_interval++; /* Rounding to correct value */   last_uptime = uptime;   /*    * A few notes about the "algorithm" used here to display selected entries    * from the system activity file (option -f with -i flag):    * Let 'Iu' be the interval value given by the user on the command line,    *     'If' the interval between current and previous line in the system    * activity file,    * and 'En' the nth entry (identified by its time stamp) of the file.    * We choose In = [ En - If/2, En + If/2 [ if If is even,    *        or In = [ En - If/2, En + If/2 ] if not.    * En will be displayed if    *       (Pn * Iu) or (P'n * Iu) belongs to In    * with  Pn = En / Iu and P'n = En / Iu + 1    */   f = (((double) ((uptime - uptime_ref) & 0xffffffff)) /	(file_hdr->sa_proc + 1)) / HZ;   entry = (unsigned long) f;   if ((f * 10) - (entry * 10) >= 5)      entry++;   min = entry - (file_interval / 2);   max = entry + (file_interval / 2) + (file_interval & 0x1);   pt1 = (entry / interval) * interval;   pt2 = ((entry / interval) + 1) * interval;   return (((pt1 >= min) && (pt1 < max)) || ((pt2 >= min) && (pt2 < max)));}/* *************************************************************************** * Use time stamp to fill tstamp structure *************************************************************************** */int decode_timestamp(char timestamp[], struct tstamp *tse){   timestamp[2] = timestamp[5] = '\0';   tse->tm_sec  = atoi(&(timestamp[6]));   tse->tm_min  = atoi(&(timestamp[3]));   tse->tm_hour = atoi(timestamp);   if ((tse->tm_sec < 0) || (tse->tm_sec > 59) ||       (tse->tm_min < 0) || (tse->tm_min > 59) ||       (tse->tm_hour < 0) || (tse->tm_hour > 23))      return 1;   tse->use = TRUE;   return 0;}/* *************************************************************************** * Compare two time stamps *************************************************************************** */int datecmp(struct tm *loc_time, struct tstamp *tse){   if (loc_time->tm_hour == tse->tm_hour) {      if (loc_time->tm_min == tse->tm_min)	return (loc_time->tm_sec - tse->tm_sec);      else	return (loc_time->tm_min - tse->tm_min);   }   else     return (loc_time->tm_hour - tse->tm_hour);}/* *************************************************************************** * Parse a time stamp entered on the command line (hh:mm:ss) *************************************************************************** */int parse_timestamp(char *argv[], int *opt, struct tstamp *tse,		    const char *def_timestamp){   char timestamp[9];   if ((argv[++(*opt)]) && (strlen(argv[*opt]) == 8))      strcpy(timestamp, argv[(*opt)++]);   else      strcpy(timestamp, def_timestamp);   return decode_timestamp(timestamp, tse);}/* *************************************************************************** * Set interval value. * g_itv is the interval in jiffies multiplied by the # of proc. * itv is the interval in jiffies. *************************************************************************** */void get_itv_value(struct file_stats *file_stats_curr,		   struct file_stats *file_stats_prev,		   unsigned int nr_proc,		   unsigned long long *itv, unsigned long long *g_itv){   /* Interval value in jiffies */   if (!file_stats_prev->uptime)      /*       * Stats from boot time to be displayed: only in this case we admit       * that the interval (which is unsigned long long) may be greater       * than 0xffffffff, else it was an overflow.       */      *g_itv = file_stats_curr->uptime;   else      *g_itv = (file_stats_curr->uptime - file_stats_prev->uptime)	 & 0xffffffff;   if (!(*g_itv))	/* Paranoia checking */      *g_itv = 1;   if (nr_proc) {      if (!file_stats_prev->uptime0)	 *itv = file_stats_curr->uptime0;      else	 *itv = (file_stats_curr->uptime0 - file_stats_prev->uptime0)	    & 0xffffffff;      if (!(*itv))	 *itv = 1;   }   else      *itv = *g_itv;}/* *************************************************************************** * Print report header *************************************************************************** */void print_report_hdr(unsigned short format, unsigned int flags,		      struct tm *loc_time, struct file_hdr *file_hdr){   if (PRINT_TRUE_TIME(flags)) {      /* Get local time */      get_localtime(loc_time);      loc_time->tm_mday = file_hdr->sa_day;      loc_time->tm_mon  = file_hdr->sa_month;      loc_time->tm_year = file_hdr->sa_year;      /*       * Call mktime() to set DST (Daylight Saving Time) flag.       * Has anyone a better way to do it?       */      loc_time->tm_hour = loc_time->tm_min = loc_time->tm_sec = 0;      mktime(loc_time);   }   else      loc_time = localtime(&(file_hdr->sa_ust_time));   if (!format)      /* No output format (we are not using sadf) */      print_gal_header(loc_time, file_hdr->sa_sysname, file_hdr->sa_release,		       file_hdr->sa_nodename);}/* *************************************************************************** * Network interfaces may now be registered (and unregistered) dynamically. * This is what we try to guess here. *************************************************************************** */unsigned int check_iface_reg(struct file_hdr *file_hdr,			     struct stats_net_dev *st_net_dev[], short curr,			     short ref, unsigned int pos){   struct stats_net_dev *st_net_dev_i, *st_net_dev_j;   unsigned int index = 0;   st_net_dev_i = st_net_dev[curr] + pos;   while (index < file_hdr->sa_iface) {      st_net_dev_j = st_net_dev[ref] + index;      if (!strcmp(st_net_dev_i->interface, st_net_dev_j->interface)) {	 /*	  * Network interface found.	  * If a counter has decreased, then we may assume that the	  * corresponding interface was unregistered, then registered again.	  */	 if ((st_net_dev_i->rx_packets < st_net_dev_j->rx_packets) ||	     (st_net_dev_i->tx_packets < st_net_dev_j->tx_packets) ||	     (st_net_dev_i->rx_bytes < st_net_dev_j->rx_bytes) ||	     (st_net_dev_i->tx_bytes < st_net_dev_j->tx_bytes) ||	     (st_net_dev_i->rx_compressed < st_net_dev_j->rx_compressed) ||	     (st_net_dev_i->tx_compressed < st_net_dev_j->tx_compressed) ||	     (st_net_dev_i->multicast < st_net_dev_j->multicast) ||	     (st_net_dev_i->rx_errors < st_net_dev_j->rx_errors) ||	     (st_net_dev_i->tx_errors < st_net_dev_j->tx_errors) ||	     (st_net_dev_i->collisions < st_net_dev_j->collisions) ||	     (st_net_dev_i->rx_dropped < st_net_dev_j->rx_dropped) ||	     (st_net_dev_i->tx_dropped < st_net_dev_j->tx_dropped) ||	     (st_net_dev_i->tx_carrier_errors < st_net_dev_j->tx_carrier_errors) ||	     (st_net_dev_i->rx_frame_errors < st_net_dev_j->rx_frame_errors) ||	     (st_net_dev_i->rx_fifo_errors < st_net_dev_j->rx_fifo_errors) ||	     (st_net_dev_i->tx_fifo_errors < st_net_dev_j->tx_fifo_errors)) {	    /*	     * Special processing for rx_bytes (_packets) and tx_bytes (_packets)	     * counters: If the number of bytes (packets) has decreased, whereas	     * the number of packets (bytes) has increased, then assume that the	     * relevant counter has met an overflow condition, and that the	     * interface was not unregistered, which is all the more plausible	     * that the previous value for the counter was > ULONG_MAX/2.	     * NB: the average value displayed will be wrong in this case...	     *	     * If such an overflow is detected, just set the flag. There is no	     * need to handle this in a special way: the difference is still	     * properly calculated if the result is of the same type (i.e.	     * unsigned long) as the two values.	     */	    int ovfw = FALSE;

⌨️ 快捷键说明

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