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

📄 common.c

📁 linux下查看系统工具原码,如IOSTAT等
💻 C
字号:
/* * sar, sadc, sadf, mpstat and iostat 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 <sys/types.h>#include <sys/ioctl.h>#include <sys/param.h>	/* for HZ *//* * For PAGE_SIZE (which may be itself a call to getpagesize()). * PAGE_SHIFT no longer necessarily exists in <asm/page.h>. So * we use PAGE_SIZE to compute PAGE_SHIFT... */#include <asm/page.h>#include "version.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/* *************************************************************************** * Print sysstat version number and exit *************************************************************************** */void print_version(void){   fprintf(stderr, _("sysstat version %s\n"		   "(C) Sebastien Godard\n"), VERSION);   exit(1);}/* *************************************************************************** * Get current date or time *************************************************************************** */time_t get_localtime(struct tm *loc_time){   time_t timer;   struct tm *ltm;   time(&timer);   ltm = localtime(&timer);   *loc_time = *ltm;   return timer;}/* *************************************************************************** * Return the number of processors used on the machine * (0 means one proc, 1 means two proc, etc.) * As far as I know, there are two possibilities for this: * 1) Use /proc/stat (this is what we are doing here) or * 2) Use /proc/cpuinfo * (I haven't heard of a better method to guess it...) *************************************************************************** */int get_cpu_nr(unsigned int max_nr_cpus){   FILE *fp;   char line[16];   int proc_nb, cpu_nr = -1;   if ((fp = fopen(STAT, "r")) == NULL) {      fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));      exit(1);   }   while (fgets(line, 16, fp) != NULL) {      if (strncmp(line, "cpu ", 4) && !strncmp(line, "cpu", 3)) {	 sscanf(line + 3, "%d", &proc_nb);	 if (proc_nb > cpu_nr)	    cpu_nr = proc_nb;      }   }   /*    * cpu_nr initial value: -1    * If cpu_nr < 0 then there is only one proc.    * If cpu_nr > 0 then this is an SMP machine.    * If cpu_nr = 0 then there is only one proc but this is a Linux 2.2 SMP or    * Linux 2.4 kernel.    */   if (cpu_nr < 0)      cpu_nr = 0;   if (cpu_nr >= max_nr_cpus) {      fprintf(stderr, _("Cannot handle so many processors!\n"));      exit(1);   }   fclose(fp);   return cpu_nr;}/* *************************************************************************** * Look for partitions of a given block device in /sys filesystem *************************************************************************** */int get_dev_part_nr(char *dev_name){   DIR *dir;   struct dirent *drd;   char dfile[MAX_PF_NAME], line[MAX_PF_NAME];   int part = 0;   sprintf(dfile, "%s/%s", SYSFS_BLOCK, dev_name);   /* Open current device directory in /sys/block */   if ((dir = opendir(dfile)) == NULL)      return 0;   /* Get current file entry */   while ((drd = readdir(dir)) != NULL) {      if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))	 continue;      sprintf(line, "%s/%s/%s", dfile, drd->d_name, S_STAT);      /* Try to guess if current entry is a directory containing a stat file */      if (!access(line, R_OK))	 /* Yep... */	 part++;   }   /* Close directory */   closedir(dir);   return part;}/* *************************************************************************** * Look for block devices present in /sys/ filesystem: * Check first that sysfs is mounted (done by trying to open /sys/block * directory), then find number of devices registered. *************************************************************************** */int get_sysfs_dev_nr(int display_partitions){   DIR *dir;   struct dirent *drd;   char line[MAX_PF_NAME];   int dev = 0;   /* Open /sys/block directory */   if ((dir = opendir(SYSFS_BLOCK)) == NULL)      /* sysfs not mounted, or perhaps this is an old kernel */      return 0;   /* Get current file entry in /sys/block directory */   while ((drd = readdir(dir)) != NULL) {      if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))	 continue;      sprintf(line, "%s/%s/%s", SYSFS_BLOCK, drd->d_name, S_STAT);      /* Try to guess if current entry is a directory containing a stat file */      if (!access(line, R_OK)) {	 /* Yep... */	 dev++;		 if (display_partitions)	    /* We also want the number of partitions for this device */	    dev += get_dev_part_nr(drd->d_name);      }   }    /* Close /sys/block directory */   closedir(dir);   return dev;}/* *************************************************************************** * Find number of devices and partitions available in /proc/diskstats. * Args: count_part : set to TRUE if devices _and_ partitions are to be *		counted. *       only_used_dev : when counting devices, set to TRUE if only devices 		with non zero stats are to be counted. *************************************************************************** */int get_diskstats_dev_nr(int count_part, int only_used_dev){   FILE *fp;   char line[256];   int dev = 0, i;   unsigned long rd_ios, wr_ios;   if ((fp = fopen(DISKSTATS, "r")) == NULL)      /* File non-existent */      return 0;   /*    * Counting devices and partitions is simply a matter of counting    * the number of lines...    */   while (fgets(line, 256, fp) != NULL) {      if (!count_part) {	 i = sscanf(line, "%*d %*d %*s %lu %*u %*u %*u %lu",		    &rd_ios, &wr_ios);	 if (i == 1)	    /* It was a partition and not a device */	    continue;	 if (only_used_dev && !rd_ios && !wr_ios)	    /* Unused device */	    continue;      }      dev++;   }   fclose(fp);   return dev;}/* *************************************************************************** * Find number of devices and partitions that have statistics in * /proc/partitions. *************************************************************************** */int get_ppartitions_dev_nr(int count_part){   FILE *fp;   char line[256];   int dev = 0;   unsigned int major, minor, tmp;   if ((fp = fopen(PPARTITIONS, "r")) == NULL)      /* File non-existent */      return 0;   while (fgets(line, 256, fp) != NULL) {      if (sscanf(line, "%u %u %*u %*s %u", &major, &minor, &tmp) == 3) {	 /*	  * We have just read a line from /proc/partitions containing stats	  * for a device or a partition (i.e. this is not a fake line:	  * header, blank line,... or a line without stats!)	  */	 if (!count_part && !ioc_iswhole(major, minor))	    /* This was a partition, and we don't want to count them */	    continue;	 dev++;      }   }   fclose(fp);   return dev;}/* *************************************************************************** * Find number of disk entries that are registered on the * "disk_io:" line in /proc/stat. *************************************************************************** */unsigned int get_disk_io_nr(void){   FILE *fp;   char line[8192];   unsigned int dsk = 0;   int pos;   if ((fp = fopen(STAT, "r")) == NULL) {      fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));      exit(2);   }   while (fgets(line, 8192, fp) != NULL) {      if (!strncmp(line, "disk_io: ", 9)) {	 for (pos = 9; pos < strlen(line) - 1; pos +=strcspn(line + pos, " ") + 1)	    dsk++;      }   }   fclose(fp);   return dsk;}/* *************************************************************************** * Print banner *************************************************************************** */inline void print_gal_header(struct tm *loc_time, char *sysname, char *release, char *nodename){   char cur_date[64];   char *e;   if (((e = getenv(TM_FMT_VAR)) != NULL) && !strcmp(e, K_ISO))      strftime(cur_date, sizeof(cur_date), "%Y-%m-%d", loc_time);   else      strftime(cur_date, sizeof(cur_date), "%x", loc_time);   printf("%s %s (%s) \t%s\n", sysname, release, nodename, cur_date);}#ifdef USE_NLS/* *************************************************************************** * Init National Language Support *************************************************************************** */void init_nls(void){   setlocale(LC_MESSAGES, "");   setlocale(LC_CTYPE, "");   setlocale(LC_TIME, "");   setlocale(LC_NUMERIC, "");   bindtextdomain(PACKAGE, LOCALEDIR);   textdomain(PACKAGE);}#endif/* *************************************************************************** * Get window height (number of lines) *************************************************************************** */int get_win_height(void){   struct winsize win;   /*    * This default value will be used whenever STDOUT    * is redirected to a pipe or a file    */   int rows = 3600 * 24;   if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1) && (win.ws_row > 2))      rows = win.ws_row - 2;   return rows;}/* *************************************************************************** * Remove /dev from path name *************************************************************************** */char *device_name(char *name){   if (!strncmp(name, "/dev/", 5))      return name + 5;   return name;}/* *************************************************************************** * Get page shift in kB *************************************************************************** */int get_kb_shift(void){   int shift = 0;   int size;   size = PAGE_SIZE >> 10; /* Assume that a page has a minimum size of 1 kB */   while (size > 1) {      shift++;      size >>= 1;   }   return shift;}/* *************************************************************************** * Handle overflow conditions properly for counters which are read as * unsigned long long, but which can be unsigned long long or * unsigned long only depending on the kernel version used. * @value1 and @value2 being two values successively read for this * counter, if @value2 < @value1 and @value1 <= 0xffffffff, then we can * assume that the counter's type was unsigned long and has overflown, and * so the difference @value2 - @value1 must be casted to this type. * NOTE: These functions should no longer be necessary to handle a particular * stat counter when we can assume that everybody is using a recent kernel * (defining this counter as unsigned long long). *************************************************************************** */double ll_sp_value(unsigned long long value1, unsigned long long value2,		   unsigned long long itv){   if ((value2 < value1) && (value1 <= 0xffffffff))      /* Counter's type was unsigned long and has overflown */      return ((double) ((value2 - value1) & 0xffffffff)) / itv * 100;   else      return SP_VALUE(value1, value2, itv);}double ll_s_value(unsigned long long value1, unsigned long long value2,		  unsigned long long itv){   if ((value2 < value1) && (value1 <= 0xffffffff))      /* Counter's type was unsigned long and has overflown */      return ((double) ((value2 - value1) & 0xffffffff)) / itv * HZ;   else      return S_VALUE(value1, value2, itv);}

⌨️ 快捷键说明

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