sadf.c

来自「linux下查看系统工具原码,如IOSTAT等」· C语言 代码 · 共 2,002 行 · 第 1/4 页

C
2,002
字号
/* *************************************************************************** * Read varying part of the statistics from a daily data file *************************************************************************** */void read_extra_stats(short curr, int ifd){   if (file_hdr.sa_proc > 0)      sa_fread(ifd, st_cpu[curr],	       STATS_ONE_CPU_SIZE * (file_hdr.sa_proc + 1), HARD_SIZE);   if (GET_ONE_IRQ(file_hdr.sa_actflag))      sa_fread(ifd, interrupts[curr],	       STATS_ONE_IRQ_SIZE, HARD_SIZE);   if (file_hdr.sa_serial)      sa_fread(ifd, st_serial[curr],	       STATS_SERIAL_SIZE * file_hdr.sa_serial, HARD_SIZE);   if (file_hdr.sa_irqcpu)      sa_fread(ifd, st_irq_cpu[curr],	       STATS_IRQ_CPU_SIZE * (file_hdr.sa_proc + 1) * file_hdr.sa_irqcpu, HARD_SIZE);   if (file_hdr.sa_iface)      sa_fread(ifd, st_net_dev[curr],	       STATS_NET_DEV_SIZE * file_hdr.sa_iface, HARD_SIZE);   if (file_hdr.sa_nr_disk)      sa_fread(ifd, st_disk[curr],	       DISK_STATS_SIZE * file_hdr.sa_nr_disk, HARD_SIZE);   /* PID stats cannot be saved in file. So we don't read them */}/* *************************************************************************** * Read stats for current activity from file *************************************************************************** */void read_curr_act_stats(int ifd, off_t fpos, short *curr, long *cnt, int *eosaf,			 unsigned int act, int *reset){   unsigned char rtype;   int next;   if (lseek(ifd, fpos, SEEK_SET) < fpos) {      perror("lseek");      exit(2);   }   /*    * Restore the first stats collected.    * Used to compute the rate displayed on the first line.    */   copy_structures(!(*curr), 2);	   *cnt  = count;   do {      /* Display <count> lines of stats */      *eosaf = sa_fread(ifd, &file_stats[*curr],			file_hdr.sa_st_size, SOFT_SIZE);      rtype = file_stats[*curr].record_type;	      if (!(*eosaf) && (rtype != R_DUMMY)) {	 /* Read the extra fields since it's not a DUMMY record */	 read_extra_stats(*curr, ifd);	 next = write_parsable_stats(*curr, act, *reset, cnt,				     tm_start.use, tm_end.use);		 if (next) {	    /*	     * next is set to 1 when we were close enough to desired interval.	     * In this case, the call to write_parsable_stats() has actually	     * displayed a line of stats.	     */	    *curr ^=1;	    if ((*cnt) > 0)	      (*cnt)--;	 }		 *reset = FALSE;      }   }   while ((*cnt) && !(*eosaf) && (rtype != R_DUMMY));   *reset = TRUE;}/* *************************************************************************** * Display activities for -x option *************************************************************************** */void xml_display_loop(int ifd){   unsigned char rtype;   short curr, tab = 0;   int eosaf = TRUE;   off_t fpos;   /* Save current file position */   if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {      perror("lseek");      exit(2);   }   /* Print XML header */   display_xml_header(&tab);   xprintf(tab, "<statistics>");   /* Process activities */   tab++;   do {      /* If this record is a DUMMY one, try to get another one */      do {	 eosaf = sa_fread(ifd, &file_stats[0], file_hdr.sa_st_size, SOFT_SIZE);	 rtype = file_stats[0].record_type;		 if (!eosaf && (rtype != R_DUMMY)) {	    /*	     * Ok: previous record was not a DUMMY one.	     * So read now the extra fields.	     */	    read_extra_stats(0, ifd);	 }      }      while (!eosaf && (rtype == R_DUMMY));      curr = 1;      if (!eosaf) {	 do {	    eosaf = sa_fread(ifd, &file_stats[curr],			     file_hdr.sa_st_size, SOFT_SIZE);	    rtype = file_stats[curr].record_type;		    if (!eosaf && (rtype != R_DUMMY)) {	       /* Read the extra fields since it's not a DUMMY record */	       read_extra_stats(curr, ifd);	       write_xml_stats(curr, &tab);	       curr ^= 1;	    }	 }	 while (!eosaf && (rtype != R_DUMMY));      }   }   while (!eosaf);   /* Rewind file */   if (lseek(ifd, fpos, SEEK_SET) < fpos) {      perror("lseek");      exit(2);   }   xprintf(--tab, "</statistics>");   xprintf(tab, "<restarts>");   /* Process now DUMMY entries to display restart messages */   tab++;   do {      if ((eosaf = sa_fread(ifd, &file_stats[0], file_hdr.sa_st_size, SOFT_SIZE)) == 0) {	 if (file_stats[0].record_type != R_DUMMY)	    read_extra_stats(0, ifd);	 else	   write_xml_restarts(0, &tab);      }   }   while (!eosaf);   xprintf(--tab, "</restarts>");   xprintf(--tab, "</host>");   xprintf(--tab, "</sysstat>");}/* *************************************************************************** * Display activities for -p and -d options *************************************************************************** */void main_display_loop(int ifd){   short curr = 1;   unsigned int act;   int eosaf = TRUE, reset = FALSE;   long cnt = 1;   off_t fpos;   /* Read system statistics from file */   do {      /*       * If this record is a DUMMY one, print it and (try to) get another one.       * We must be sure that we have real stats in file_stats[2].       */      do {	 if (sa_fread(ifd, &file_stats[0], file_hdr.sa_st_size, SOFT_SIZE))	    /* End of sa data file */	    return;		 if (file_stats[0].record_type == R_DUMMY)	    write_dummy(0, tm_start.use, tm_end.use);	 else {	    /*	     Ok: previous record was not a DUMMY one. So read now the extra fields. */	    read_extra_stats(0, ifd);	    set_loc_time(0);	 }      }      while ((file_stats[0].record_type == R_DUMMY) ||	     (tm_start.use && (datecmp(&loc_time, &tm_start) < 0)) ||	     (tm_end.use && (datecmp(&loc_time, &tm_end) >=0)));      /* Save the first stats collected. Will be used to compute the average */      copy_structures(2, 0);      reset = TRUE;	/* Set flag to reset last_uptime variable */      /* Save current file position */      if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {	 perror("lseek");	 exit(2);      }      /* Read and write stats located between two possible Linux restarts */      /* For each requested activity... */      for (act = 1; act <= A_LAST; act <<= 1) {	 if (sadf_actflag & act) {	    if ((act == A_IRQ) && WANT_PER_PROC(flags) && WANT_ALL_PROC(flags)) {	       /* Distinguish -I SUM activity from IRQs per processor activity */	       flags &= ~S_F_PER_PROC;	       read_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act, &reset);	       flags |= S_F_PER_PROC;	       flags &= ~S_F_ALL_PROC;	       read_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act, &reset);	       flags |= S_F_ALL_PROC;	    }	    else	       read_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act, &reset);	 }      }      if (!cnt) {	 /* Go to next Linux restart, if possible */	 do {	    eosaf = sa_fread(ifd, &file_stats[curr],			     file_hdr.sa_st_size, SOFT_SIZE);	    if (!eosaf && (file_stats[curr].record_type != R_DUMMY))	       read_extra_stats(curr, ifd);	 }	 while (!eosaf && (file_stats[curr].record_type != R_DUMMY));      }      /* The last record we read was a DUMMY one: print it */      if (!eosaf && (file_stats[curr].record_type == R_DUMMY))	 write_dummy(curr, tm_start.use, tm_end.use);   }   while (!eosaf);}/* *************************************************************************** * Read statistics from a system activity data file *************************************************************************** */void read_stats_from_file(char dfile[]){   int ifd;   /* Prepare file for reading */   prep_file_for_reading(&ifd, dfile, &file_hdr, &sadf_actflag, flags);   if (format == S_O_HDR_OPTION) {      /* Display data file header */      display_file_header(dfile, &file_hdr);      return;   }   /* Perform required allocations */   allocate_structures(USE_SA_FILE);   /* Print report header if needed */   print_report_hdr(format, flags, &loc_time, &file_hdr);   if (format == S_O_XML_OPTION)     xml_display_loop(ifd);   else     main_display_loop(ifd);   close(ifd);}/* *************************************************************************** * Main entry to the sadf program *************************************************************************** */int main(int argc, char **argv){   int opt = 1, sar_options = 0;   int i;   char dfile[MAX_FILE_LEN];   short dum;   /* Compute page shift in kB */   kb_shift = get_kb_shift();   dfile[0] = '\0';#ifdef USE_NLS   /* Init National Language Support */   init_nls();#endif   tm_start.use = tm_end.use = FALSE;   init_bitmap(irq_bitmap, 0, NR_IRQS);   init_bitmap(cpu_bitmap, 0, NR_CPUS);   init_stats(file_stats, interrupts);   /* Process options */   while (opt < argc) {      if (!strcmp(argv[opt], "-I")) {	 if (argv[++opt] && sar_options) {	    if (parse_sar_I_opt(argv, &opt, &sadf_actflag, &dum,				irq_bitmap))	       usage(argv[0]);	 }	 else	    usage(argv[0]);      }      else if (!strcmp(argv[opt], "-P")) {	 if (parse_sa_P_opt(argv, &opt, &flags, &dum, cpu_bitmap))	    usage(argv[0]);      }      else if (!strcmp(argv[opt], "-s")) {	 /* Get time start */	 if (parse_timestamp(argv, &opt, &tm_start, DEF_TMSTART))	    usage(argv[0]);      }      else if (!strcmp(argv[opt], "-e")) {	 /* Get time end */	 if (parse_timestamp(argv, &opt, &tm_end, DEF_TMEND))	    usage(argv[0]);      }      else if (!strcmp(argv[opt], "--")) {	 sar_options = 1;	 opt++;      }      else if (!strcmp(argv[opt], "-n")) {	 if (argv[++opt] && sar_options) {	    /* Parse sar's option -n */	    if (parse_sar_n_opt(argv, &opt, &sadf_actflag, &dum))	       usage(argv[0]);	 }	 else	    usage(argv[0]);      }      else if (!strncmp(argv[opt], "-", 1)) {	 /* Other options not previously tested */	 if (sar_options) {	    if (parse_sar_opt(argv, opt, &sadf_actflag, &flags, &dum, C_SADF,			      irq_bitmap, cpu_bitmap))	       usage(argv[0]);	 }	 else {	    for (i = 1; *(argv[opt] + i); i++) {	       switch (*(argv[opt] + i)) {			case 'd':		  if (format && (format != S_O_DB_OPTION))		     usage(argv[0]);		  format = S_O_DB_OPTION;		  break;		case 'H':		  if (format && (format != S_O_HDR_OPTION))		     usage(argv[0]);		  format = S_O_HDR_OPTION;		  break;		case 'p':		  if (format && (format != S_O_PPC_OPTION))		     usage(argv[0]);		  format = S_O_PPC_OPTION;		  break;		case 't':		  flags |= S_F_TRUE_TIME;		  break;		case 'x':		  if (format && (format != S_O_XML_OPTION))		     usage(argv[0]);		  format = S_O_XML_OPTION;		  break;		case 'V':		  print_version();		  break;		default:		  usage(argv[0]);	       }	    }	 }	 opt++;      }	      /* Get data file name */      else if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {	 if (!dfile[0]) {	    if (!strcmp(argv[opt], "-")) {	       /* File name set to '-' */	       get_localtime(&loc_time);	       snprintf(dfile, MAX_FILE_LEN,			"%s/sa%02d", SA_DIR, loc_time.tm_mday);	       dfile[MAX_FILE_LEN - 1] = '\0';	       opt++;	    }	    else if (!strncmp(argv[opt], "-", 1))	       /* Bad option */	       usage(argv[0]);	    else {	       /* Write data to file */	       strncpy(dfile, argv[opt++], MAX_FILE_LEN);	       dfile[MAX_FILE_LEN - 1] = '\0';	    }	 }	 else	    /* File already specified */	    usage(argv[0]);      }      else if (interval < 0) { 		/* Get interval */	 if (strspn(argv[opt], DIGITS) != strlen(argv[opt]))	    usage(argv[0]);	 interval = atol(argv[opt++]);	 if (interval <= 0)	   usage(argv[0]);      }      else {				/* Get count value */	 if (strspn(argv[opt], DIGITS) != strlen(argv[opt]))	    usage(argv[0]);	 if (count)	    /* Count parameter already set */	    usage(argv[0]);	 count = atol(argv[opt++]);	 if (count < 0)	   usage(argv[0]);	 else if (!count)	    count = -1;	/* To generate a report continuously */      }   }   /* sadf reads current daily data file by default */   if (!dfile[0]) {      get_localtime(&loc_time);      snprintf(dfile, MAX_FILE_LEN,	       "%s/sa%02d", SA_DIR, loc_time.tm_mday);      dfile[MAX_FILE_LEN - 1] = '\0';   }   /*    * Display all the contents of the daily data file if the count parameter    * was not set on the command line.    */   if (!count)      count = -1;   /*    * Default is CPU activity and PPC display.    * For XML display, activity flag is meaningless since every activity will    * be displayed. So make sure that sadf won't complain about non existent    * activities in file...    */   if (!sadf_actflag || (format == S_O_XML_OPTION))      sadf_actflag |= A_CPU;   if (!format)      format = S_O_PPC_OPTION;   if (interval < 0)      interval = 1;   /* Read stats from file */   read_stats_from_file(dfile);   return 0;}

⌨️ 快捷键说明

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