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

📄 sar.c

📁 linux下查看系统工具原码,如IOSTAT等
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * sar: report system activity * (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 <unistd.h>#include <time.h>#include <errno.h>#include <sys/param.h>	/* for HZ */#include "sa.h"#include "common.h"#ifdef USE_NLS#include <locale.h>#include <libintl.h>#define _(string) gettext(string)#else#define _(string) (string)#endiflong interval = -1, count = 0;unsigned int sar_actflag = 0;unsigned int flags = 0;unsigned char irq_bitmap[(NR_IRQS / 8) + 1];unsigned char cpu_bitmap[(NR_CPUS / 8) + 1];int kb_shift = 0;struct stats_sum asum;struct file_hdr file_hdr;struct file_stats file_stats[DIM];struct stats_one_cpu *st_cpu[DIM] = {NULL, NULL, NULL};struct stats_serial *st_serial[DIM] = {NULL, NULL, NULL};struct stats_irq_cpu *st_irq_cpu[DIM] = {NULL, NULL, NULL};struct stats_net_dev *st_net_dev[DIM] = {NULL, NULL, NULL};struct disk_stats *st_disk[DIM] = {NULL, NULL, NULL};/* Array members of common types are always packed */unsigned int interrupts[DIM][NR_IRQS];/* Structures are aligned but also padded. Thus array members are packed */struct pid_stats *pid_stats[DIM][MAX_PID_NR];struct tm loc_time;/* Contain the date specified by -s and -e options */struct tstamp tm_start, tm_end;short dis_hdr = -1;int pid_nr = 0;char *args[MAX_ARGV_NR];/* *************************************************************************** * Print usage and exit *************************************************************************** */void usage(char *progname){   fprintf(stderr, _("Usage: %s [ options... ] [ <interval> [ <count> ] ]\n"	           "Options are:\n"	           "[ -A ] [ -b ] [ -B ] [ -c ] [ -d ] [ -i <interval> ] [ -p ] [ -q ]\n"		   "[ -r ] [ -R ] [ -t ] [ -u ] [ -v ] [ -V ] [ -w ] [ -W ] [ -y ]\n"		   "[ -I { <irq> | SUM | ALL | XALL } ] [ -P { <cpu> | ALL } ]\n"		   "[ -n { DEV | EDEV | NFS | NFSD | SOCK | ALL } ]\n"		   "[ -x { <pid> | SELF | ALL } ] [ -X { <pid> | SELF | ALL } ]\n"	           "[ -o [ <filename> ] | -f [ <filename> ] ]\n"		   "[ -s [ <hh:mm:ss> ] ] [ -e [ <hh:mm:ss> ] ]\n"),	   progname);   exit(1);}/* *************************************************************************** * Init stats structures *************************************************************************** */void init_all_stats(void){   int i;   init_stats(file_stats, interrupts);   memset(&asum, 0, STATS_SUM_SIZE);   for (i = 0; i < DIM; i++)      pid_stats[i][0] = NULL;}/* *************************************************************************** * Allocate memory for sadc args *************************************************************************** */void salloc(int i, char *ltemp){   if ((args[i] = (char *) malloc(strlen(ltemp) + 1)) == NULL) {      perror("malloc");      exit(4);   }   strcpy(args[i], ltemp);}/* *************************************************************************** * Allocate pid_stats structures *************************************************************************** */void salloc_pid(int nr_pid){   int i, pid;   for (i = 0; i < DIM; i++) {      if (pid_stats[i][0])	 free(pid_stats[i][0]);      if ((pid_stats[i][0] = (struct pid_stats *) malloc(PID_STATS_SIZE * nr_pid)) == NULL) {	 perror("malloc");	 exit(4);      }      memset(pid_stats[i][0], 0, PID_STATS_SIZE * nr_pid);      for (pid = 1; pid < nr_pid; pid++)	 /* Structures are aligned but also padded. Thus array members are packed */	 pid_stats[i][pid] = pid_stats[i][0] + pid;	/* Assume nr_pids <= MAX_PID_NR */   }}/* *************************************************************************** * Allocate structures *************************************************************************** */void allocate_structures(int stype){   if (file_hdr.sa_proc > 0)      salloc_cpu_array(st_cpu, file_hdr.sa_proc + 1);   if ((stype == USE_SADC) &&       (GET_PID(sar_actflag) || GET_CPID(sar_actflag))) {      pid_nr = file_hdr.sa_nr_pid;      salloc_pid(pid_nr);   }   if (file_hdr.sa_serial)      salloc_serial_array(st_serial, file_hdr.sa_serial);   if (file_hdr.sa_irqcpu)      salloc_irqcpu_array(st_irq_cpu, file_hdr.sa_proc + 1, file_hdr.sa_irqcpu);   if (file_hdr.sa_iface)      salloc_net_dev_array(st_net_dev, file_hdr.sa_iface);   if (file_hdr.sa_nr_disk)      salloc_disk_array(st_disk, file_hdr.sa_nr_disk);}/* *************************************************************************** * Check if the user has the right to use -P option. * Note that he may use this option when reading stats from a file, * even if his machine is not an SMP one... * This routine is called only if we are *not* reading stats from a file. *************************************************************************** */void check_smp_option(unsigned int cpu_nr){   unsigned int j = 0, i;   if (cpu_nr == 0) {      fprintf(stderr, _("Not an SMP machine...\n"));      exit(1);   }   for (i = (cpu_nr + 1); i < NR_CPUS; i++)      j |= cpu_bitmap[i >> 3] & (1 << (i & 0x07));   if (j) {      fprintf(stderr, _("Not that many processors!\n"));      exit(1);   }}/* *************************************************************************** * Check the use of option -P. * Called only if reading stats sent by the data collector. *************************************************************************** */void prep_smp_option(unsigned int cpu_nr){   unsigned int i;   if (WANT_PER_PROC(flags)) {      if (WANT_ALL_PROC(flags))	 for (i = cpu_nr + 1; i < ((NR_CPUS >> 3) + 1) << 3; i++)	    /*	     * Reset every bit for proc > cpu_nr	     * (only done when -P ALL entered on the command line)	     */	    cpu_bitmap[i >> 3] &= ~(1 << (i & 0x07));      check_smp_option(cpu_nr);   }}/* *************************************************************************** * Fill loc_time structure according to time data saved in current * structure. ****************************************************************************/void set_loc_time(short curr){   struct tm *ltm;   /* NOTE: loc_time structure must have been init'ed before! */   /* Check if option -t was specified on the command line */   if (PRINT_TRUE_TIME(flags)) {      /* -t */      loc_time.tm_hour = file_stats[curr].hour;      loc_time.tm_min  = file_stats[curr].minute;      loc_time.tm_sec  = file_stats[curr].second;   }   else {      ltm = localtime(&file_stats[curr].ust_time);      loc_time = *ltm;   }}/* *************************************************************************** * Set timestamp string ****************************************************************************/void set_timestamp(short curr, char *cur_time, int len){   set_loc_time(curr);   /* Set cur_time date value */   strftime(cur_time, len, "%X", &loc_time);}/* *************************************************************************** * Core function used to display statistics *************************************************************************** */void write_stats_core(short prev, short curr, short dis, char *prev_string,		      char *curr_string, unsigned int act,		      unsigned long long itv, unsigned long long g_itv,		      int disp_avg, int want_since_boot){   int i, j = 0, k;   struct file_stats      *fsi = &file_stats[curr],      *fsj = &file_stats[prev];   /*    * Under very special circumstances, STDOUT may become unavailable,    * This is what we try to guess here    */   if (write(STDOUT_FILENO, "", 0) == -1) {      perror("stdout");      exit(6);   }   /* Print number of processes created per second */   if (GET_PROC(act)) {      if (dis)	 printf("\n%-11s    proc/s\n", prev_string);      printf("%-11s %9.2f\n", curr_string,	     S_VALUE(fsj->processes, fsi->processes, itv));   }   /* Print number of context switches per second */   if (GET_CTXSW(act)) {      if (dis)	 printf("\n%-11s   cswch/s\n", prev_string);      printf("%-11s %9.2f\n", curr_string,	     ll_s_value(fsj->context_swtch, fsi->context_swtch, itv));   }   /* Print CPU usage */   if (GET_CPU(act)) {      if (dis)	 printf("\n%-11s       CPU     %%user     %%nice   %%system   "		"%%iowait    %%steal     %%idle\n",		prev_string);      if (!WANT_PER_PROC(flags) ||	  (WANT_PER_PROC(flags) && WANT_ALL_PROC(flags))) {	 printf("%-11s       all", curr_string);	 printf("    %6.2f    %6.2f    %6.2f    %6.2f    %6.2f",		ll_sp_value(fsj->cpu_user, fsi->cpu_user, g_itv),		ll_sp_value(fsj->cpu_nice, fsi->cpu_nice, g_itv),		ll_sp_value(fsj->cpu_system, fsi->cpu_system, g_itv),		ll_sp_value(fsj->cpu_iowait, fsi->cpu_iowait, g_itv),		ll_sp_value(fsj->cpu_steal, fsi->cpu_steal, g_itv));	 printf("    %6.2f\n",		fsi->cpu_idle < fsj->cpu_idle ? /* Handle buggy kernels */		0.0 : ll_sp_value(fsj->cpu_idle, fsi->cpu_idle, g_itv));      }      if (WANT_PER_PROC(flags) && file_hdr.sa_proc) {	 unsigned long long pc_itv;	 struct stats_one_cpu	    *sci = st_cpu[curr],	    *scj = st_cpu[prev];		 for (i = 0; i <= file_hdr.sa_proc; i++, sci++, scj++) {	    if (cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {	       printf("%-11s       %3d", curr_string, i);		       /* Recalculate itv for current proc */	       pc_itv = get_per_cpu_interval(sci, scj);		       printf("    %6.2f    %6.2f    %6.2f    %6.2f    %6.2f",		      ll_sp_value(scj->per_cpu_user, sci->per_cpu_user, pc_itv),		      ll_sp_value(scj->per_cpu_nice, sci->per_cpu_nice, pc_itv),		      ll_sp_value(scj->per_cpu_system, sci->per_cpu_system, pc_itv),		      ll_sp_value(scj->per_cpu_iowait, sci->per_cpu_iowait, pc_itv),		      ll_sp_value(scj->per_cpu_steal, sci->per_cpu_steal, pc_itv));	       printf("    %6.2f\n",		      sci->per_cpu_idle < scj->per_cpu_idle ?		      0.0 : ll_sp_value(scj->per_cpu_idle, sci->per_cpu_idle, pc_itv));	    }	 }      }   }   if (GET_IRQ(act) &&       (!WANT_PER_PROC(flags) ||	(WANT_PER_PROC(flags) && WANT_ALL_PROC(flags)))) {	 if (dis)	    printf("\n%-11s      INTR    intr/s\n", prev_string);	 /* Print number of interrupts per second */	 printf("%-11s       sum", curr_string);	 printf(" %9.2f\n",		ll_s_value(fsj->irq_sum, fsi->irq_sum, itv));   }   if (GET_ONE_IRQ(act)) {      if (dis)	 printf("\n%-11s      INTR    intr/s\n", prev_string);      /* Print number of interrupts per second */      for (i = 0; i < NR_IRQS; i++) {	 if (irq_bitmap[i >> 3] & (1 << (i & 0x07))) {	    printf("%-11s       %3d", curr_string, i);	    printf(" %9.2f\n",		   S_VALUE(interrupts[prev][i], interrupts[curr][i], itv));	 }      }   }   /* Print paging statistics */   if (GET_PAGE(act)) {      if (dis)	 printf("\n%-11s  pgpgin/s pgpgout/s   fault/s  majflt/s\n",		prev_string);      printf("%-11s %9.2f %9.2f %9.2f %9.2f\n", curr_string,	     S_VALUE(fsj->pgpgin, fsi->pgpgin, itv),	     S_VALUE(fsj->pgpgout, fsi->pgpgout, itv),	     S_VALUE(fsj->pgfault, fsi->pgfault, itv),	     S_VALUE(fsj->pgmajfault, fsi->pgmajfault, itv));   }   /* Print number of swap pages brought in and out */   if (GET_SWAP(act)) {      if (dis)	 printf("\n%-11s  pswpin/s pswpout/s\n", prev_string);      printf("%-11s %9.2f %9.2f\n", curr_string,	     S_VALUE(fsj->pswpin, fsi->pswpin, itv),	     S_VALUE(fsj->pswpout, fsi->pswpout, itv));   }   /* Print I/O stats (no distinction made between disks) */   if (GET_IO(act)) {      if (dis)	 printf("\n%-11s       tps      rtps      wtps   bread/s   bwrtn/s\n",		prev_string);      printf("%-11s %9.2f %9.2f %9.2f %9.2f %9.2f\n", curr_string,	     S_VALUE(fsj->dk_drive, fsi->dk_drive, itv),	     S_VALUE(fsj->dk_drive_rio, fsi->dk_drive_rio, itv),	     S_VALUE(fsj->dk_drive_wio, fsi->dk_drive_wio, itv),	     S_VALUE(fsj->dk_drive_rblk, fsi->dk_drive_rblk, itv),	     S_VALUE(fsj->dk_drive_wblk, fsi->dk_drive_wblk, itv));   }   /* Print memory stats */   if (GET_MEMORY(act)) {      if (dis)	 printf("\n%-11s   frmpg/s   bufpg/s   campg/s\n", prev_string);      printf("%-11s %9.2f %9.2f %9.2f\n", curr_string,	     S_VALUE((double) PG(fsj->frmkb), (double) PG(fsi->frmkb), itv),	     S_VALUE((double) PG(fsj->bufkb), (double) PG(fsi->bufkb), itv),	     S_VALUE((double) PG(fsj->camkb), (double) PG(fsi->camkb), itv));   }   /* Print per-process statistics */   if (GET_PID(act)) {      if (dis) {	 printf("\n%-11s       PID  minflt/s  majflt/s     %%user   %%system   nswap/s",		prev_string);	 if (!disp_avg)	    printf("   CPU\n");	 else	    printf("\n");      }      for (i = 0; i < pid_nr; i++) {	 if (!pid_stats[curr][i]->pid || !(pid_stats[curr][i]->flag & X_PID_SET))	    continue; 	 printf("%-11s %9ld", curr_string, pid_stats[curr][i]->pid);	 printf(" %9.2f %9.2f    %6.2f    %6.2f %9.2f",		S_VALUE(pid_stats[prev][i]->minflt, pid_stats[curr][i]->minflt, itv),		S_VALUE(pid_stats[prev][i]->majflt, pid_stats[curr][i]->majflt, itv),		SP_VALUE(pid_stats[prev][i]->utime, pid_stats[curr][i]->utime, itv),		SP_VALUE(pid_stats[prev][i]->stime, pid_stats[curr][i]->stime, itv),		S_VALUE((long) pid_stats[prev][i]->nswap,

⌨️ 快捷键说明

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