📄 sadc.c
字号:
int nb; struct tm loc_time; /* Check if file is locked */ if (!FILE_LOCKED(*flags)) ask_for_flock(ofd, flags, FATAL); /* Reset the structure (not compulsory, but a bit cleaner */ memset(&file_stats, 0, FILE_STATS_SIZE); file_stats.record_type = R_DUMMY; /* Save time */ file_stats.ust_time = get_localtime(&loc_time); file_stats.hour = loc_time.tm_hour; file_stats.minute = loc_time.tm_min; file_stats.second = loc_time.tm_sec; /* Write record now */ if ((nb = write(ofd, &file_stats, file_stats_size)) != file_stats_size) p_write_error();}/* *************************************************************************** * Write stats. * NB: sadc provides all the stats, including: * -> CPU utilization per processor (on SMP machines only) * -> IRQ per processor (on SMP machines only) * -> number of each IRQ (if -I option passed to sadc), including APIC * interrupts sources * -> device stats for sar -d (kernels 2.4 and newer only, and only if * -d option passed to sadc) *************************************************************************** */void write_stats(int ofd, size_t file_stats_size, unsigned int *flags){ int nb; /* Try to lock file */ if (!FILE_LOCKED(*flags)) { if (ask_for_flock(ofd, flags, NON_FATAL)) /* Unable to lock file: wait for next iteration to try again to save data */ return; } if ((nb = write(ofd, &file_stats, file_stats_size)) != file_stats_size) p_write_error(); if (cpu_nr > 0) { if ((nb = write(ofd, st_cpu, STATS_ONE_CPU_SIZE * (cpu_nr + 1))) != (STATS_ONE_CPU_SIZE * (cpu_nr + 1))) p_write_error(); } if (GET_ONE_IRQ(sadc_actflag)) { if ((nb = write(ofd, interrupts, STATS_ONE_IRQ_SIZE)) != STATS_ONE_IRQ_SIZE) p_write_error(); } if (pid_nr) { /* Structures are packed together! */ if ((nb = write(ofd, pid_stats[0], PID_STATS_SIZE * pid_nr)) != (PID_STATS_SIZE * pid_nr)) p_write_error(); } if (serial_nr) { if ((nb = write(ofd, st_serial, STATS_SERIAL_SIZE * serial_nr)) != (STATS_SERIAL_SIZE * serial_nr)) p_write_error(); } if (irqcpu_nr) { if ((nb = write(ofd, st_irq_cpu, STATS_IRQ_CPU_SIZE * (cpu_nr + 1) * irqcpu_nr)) != (STATS_IRQ_CPU_SIZE * (cpu_nr + 1) * irqcpu_nr)) p_write_error(); } if (iface_nr) { if ((nb = write(ofd, st_net_dev, STATS_NET_DEV_SIZE * iface_nr)) != (STATS_NET_DEV_SIZE * iface_nr)) p_write_error(); } if (disk_nr && GET_DISK(sadc_actflag)) { /* Disk stats written only if -d option used */ if ((nb = write(ofd, st_disk, DISK_STATS_SIZE * disk_nr)) != (DISK_STATS_SIZE * disk_nr)) p_write_error(); }}/* *************************************************************************** * Create a system activity daily data file *************************************************************************** */void create_sa_file(int *ofd, char *ofile, size_t *file_stats_size, unsigned int *flags){ if ((*ofd = open(ofile, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { fprintf(stderr, _("Cannot open %s: %s\n"), ofile, strerror(errno)); exit(2); } /* Try to lock file */ ask_for_flock(*ofd, flags, FATAL); /* Truncate file */ if (ftruncate(*ofd, 0) < 0) { fprintf(stderr, _("Cannot open %s: %s\n"), ofile, strerror(errno)); exit(2); } /* Write file header */ setup_file_hdr(*ofd, file_stats_size);}/* *************************************************************************** * Get descriptor for stdout. *************************************************************************** */void open_stdout(int *stdfd, size_t *file_stats_size){ if (*stdfd >= 0) { if ((*stdfd = dup(STDOUT_FILENO)) < 0) { perror("dup"); exit(4); } /* Write file header on STDOUT */ setup_file_hdr(*stdfd, file_stats_size); }}/* *************************************************************************** * Get descriptor for output file and write its header. * We may enter this function several times (when we rotate a file). *************************************************************************** */void open_ofile(int *ofd, char ofile[], size_t *file_stats_size, unsigned int *flags){ ssize_t size; if (ofile[0]) { /* Does file exist? */ if (access(ofile, F_OK) < 0) /* NO: create it */ create_sa_file(ofd, ofile, file_stats_size, flags); else { /* YES: append data to it if possible */ if ((*ofd = open(ofile, O_APPEND | O_RDWR)) < 0) { fprintf(stderr, _("Cannot open %s: %s\n"), ofile, strerror(errno)); exit(2); } /* Read file header */ size = read(*ofd, &file_hdr, FILE_HDR_SIZE); if (!size) { close(*ofd); /* This is an empty file: create it again */ create_sa_file(ofd, ofile, file_stats_size, flags); return; } if ((size != FILE_HDR_SIZE) || (file_hdr.sa_magic != SA_MAGIC)) { close(*ofd); if (USE_F_OPTION(*flags)) { /* -F option used: Truncate file */ create_sa_file(ofd, ofile, file_stats_size, flags); return; } fprintf(stderr, _("Invalid system activity file: %s (%#x)\n"), ofile, file_hdr.sa_magic); exit(3); } /* * Ok: it's a true system activity file. * File activity flag prevails over that of the user * e.g. for the A_ONE_IRQ activity... * Same thing with file file_stats size. */ sadc_actflag = file_hdr.sa_actflag; *file_stats_size = file_hdr.sa_st_size; if (file_hdr.sa_proc != cpu_nr) { close(*ofd); if (USE_F_OPTION(*flags)) { create_sa_file(ofd, ofile, file_stats_size, flags); return; } fprintf(stderr, _("Cannot append data to that file\n")); exit(1); } /* * Force characteristics (nb of serial lines, network interfaces...) * to that of the file. */ if (file_hdr.sa_serial != serial_nr) { serial_nr = file_hdr.sa_serial; SREALLOC(st_serial, struct stats_serial, STATS_SERIAL_SIZE * serial_nr); } if (file_hdr.sa_iface != iface_nr) { iface_nr = file_hdr.sa_iface; SREALLOC(st_net_dev, struct stats_net_dev, STATS_NET_DEV_SIZE * iface_nr); } if (file_hdr.sa_irqcpu != irqcpu_nr) { irqcpu_nr = file_hdr.sa_irqcpu; SREALLOC(st_irq_cpu, struct stats_irq_cpu, STATS_IRQ_CPU_SIZE * (cpu_nr + 1) * irqcpu_nr); } if (file_hdr.sa_nr_disk != disk_nr) { if (!file_hdr.sa_nr_disk) /* Remove use of option -d */ sadc_actflag &= ~A_DISK; else { disk_nr = file_hdr.sa_nr_disk; SREALLOC(st_disk, struct disk_stats, DISK_STATS_SIZE * disk_nr); } } } }}/* *************************************************************************** * Read stats from /proc/stat *************************************************************************** */void read_proc_stat(unsigned int flags){ FILE *fp; struct stats_one_cpu *st_cpu_i; struct disk_stats *st_disk_i; static char line[8192]; unsigned long long cc_user, cc_nice, cc_system, cc_hardirq, cc_softirq; unsigned long long cc_idle, cc_iowait, cc_steal; unsigned int v_tmp[5], v_major, v_index; int proc_nb, i, 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, "cpu ", 4)) { /* * Read the number of jiffies spent in the different modes * (user, nice, etc.) among all proc. CPU usage is not reduced * to one processor to avoid rounding problems. */ file_stats.cpu_iowait = 0; /* For pre 2.5 kernels */ file_stats.cpu_steal = 0; cc_hardirq = cc_softirq = 0; sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu", &(file_stats.cpu_user), &(file_stats.cpu_nice), &(file_stats.cpu_system), &(file_stats.cpu_idle), &(file_stats.cpu_iowait), &cc_hardirq, &cc_softirq, &(file_stats.cpu_steal)); /* * Time spent in system mode also includes time spent * servicing hard interrrupts and softirqs. */ file_stats.cpu_system += cc_hardirq + cc_softirq; /* * Compute the uptime of the system in jiffies (1/100ths of a second * if HZ=100). * Machine uptime is multiplied by the number of processors here. * Note that overflow is not so far away: ULONG_MAX is 4294967295 on * 32 bit systems. Overflow happens when machine uptime is: * 497 days on a monoprocessor machine, * 248 days on a bi processor, * 124 days on a quad processor... */ file_stats.uptime = file_stats.cpu_user + file_stats.cpu_nice + file_stats.cpu_system + file_stats.cpu_idle + file_stats.cpu_iowait + file_stats.cpu_steal; } else if (!strncmp(line, "cpu", 3)) { if (cpu_nr > 0) { /* * Read the number of jiffies spent in the different modes * (user, nice, etc) for current proc. * This is done only on SMP machines. * Warning: st_cpu_i struct is _not_ allocated even if the kernel * has SMP support enabled. */ cc_iowait = cc_steal = 0; /* For pre 2.5 kernels */ cc_hardirq = cc_softirq = 0; sscanf(line + 3, "%d %llu %llu %llu %llu %llu %llu %llu %llu", &proc_nb, &cc_user, &cc_nice, &cc_system, &cc_idle, &cc_iowait, &cc_hardirq, &cc_softirq, &cc_steal); cc_system += cc_hardirq + cc_softirq; if (proc_nb <= cpu_nr) { st_cpu_i = st_cpu + proc_nb; st_cpu_i->per_cpu_user = cc_user; st_cpu_i->per_cpu_nice = cc_nice; st_cpu_i->per_cpu_system = cc_system; st_cpu_i->per_cpu_idle = cc_idle; st_cpu_i->per_cpu_iowait = cc_iowait; st_cpu_i->per_cpu_steal = cc_steal; } /* else: * Additional CPUs have been dynamically registered in /proc/stat. * sar won't crash, but the CPU stats might be false... */ if (!proc_nb) /* Compute uptime reduced to one proc using proc#0 */ file_stats.uptime0 = cc_user + cc_nice + cc_system + cc_idle + cc_iowait + cc_steal; } } else if (!strncmp(line, "page ", 5)) /* Read number of pages the system paged in and out */ sscanf(line + 5, "%lu %lu", &(file_stats.pgpgin), &(file_stats.pgpgout)); else if (!strncmp(line, "swap ", 5)) /* Read number of swap pages brought in and out */ sscanf(line + 5, "%lu %lu", &(file_stats.pswpin), &(file_stats.pswpout)); else if (!strncmp(line, "intr ", 5)) { /* Read total number of interrupts received since system boot */ sscanf(line + 5, "%llu", &(file_stats.irq_sum)); pos = strcspn(line + 5, " ") + 5; if (GET_ONE_IRQ(sadc_actflag)) { /* * If -I option set on the command line, * read number of each interrupts received since system boot. */ for (i = 0; i < NR_IRQS; i++) { sscanf(line + pos, " %u", &interrupts[i]); pos += strcspn(line + pos + 1, " ") + 1; } } } else if (!strncmp(line, "ctxt ", 5)) /* Read number of context switches */ sscanf(line + 5, "%llu", &(file_stats.context_swtch)); else if (!strncmp(line, "processes ", 10)) /* Read number of processes created since system boot */ sscanf(line + 10, "%lu", &(file_stats.processes)); else if (!HAS_DISKSTATS(flags) && !HAS_PPARTITIONS(flags)) { /* * Read possible disk stats from /proc/stat only if we are * sure they won't be read later from /proc/diskstats or * /proc/partitions. */ if (!strncmp(line, "disk ", 5)) { /* Read number of I/O done since the last reboot */ sscanf(line + 5, "%u %u %u %u", &(file_stats.dk_drive), &u_tmp[0], &u_tmp[1], &u_tmp[2]); file_stats.dk_drive += u_tmp[0] + u_tmp[1] + u_tmp[2]; } else if (!strncmp(line, "disk_rio ", 9)) { /* Read number of read I/O */ sscanf(line + 9, "%u %u %u %u", &(file_stats.dk_drive_rio), &u_tmp[0], &u_tmp[1], &u_tmp[2]); file_stats.dk_drive_rio += u_tmp[0] + u_tmp[1] + u_tmp[2]; } else if (!strncmp(line, "disk_wio ", 9)) { /* Read number of write I/O */ sscanf(line + 9, "%u %u %u %u", &(file_stats.dk_drive_wio), &u_tmp[0], &u_tmp[1], &u_tmp[2]); file_stats.dk_drive_wio += u_tmp[0] + u_tmp[1] + u_tmp[2]; } else if (!strncmp(line, "disk_rblk ", 10)) { /* Read number of blocks read from disk */ sscanf(line + 10, "%u %u %u %u", &(file_stats.dk_drive_rblk), &u_tmp[0], &u_tmp[1], &u_tmp[2]); file_stats.dk_drive_rblk += u_tmp[0] + u_tmp[1] + u_tmp[2]; } else if (!strncmp(line, "disk_wblk ", 10)) { /* Read number of blocks written to disk */ sscanf(line + 10, "%u %u %u %u", &(file_stats.dk_drive_wblk), &u_tmp[0], &u_tmp[1], &u_tmp[2]); file_stats.dk_drive_wblk += u_tmp[0] + u_tmp[1] + u_tmp[2]; } else if (!strncmp(line, "disk_io: ", 9)) { unsigned int dsk = 0; init_dk_drive_stat(); pos = 9; /* Read disks I/O statistics (for 2.4 kernels) */ while (pos < strlen(line) - 1) { /* Beware: a CR is already included in the line */ sscanf(line + pos, "(%u,%u):(%u,%u,%u,%u,%u) ", &v_major, &v_index, &v_tmp[0], &v_tmp[1], &v_tmp[2], &v_tmp[3], &v_tmp[4]); file_stats.dk_drive += v_tmp[0]; file_stats.dk_drive_rio += v_tmp[1]; file_stats.dk_drive_rblk += v_tmp[2]; file_stats.dk_drive_wio += v_tmp[3]; file_stats.dk_drive_wblk += v_tmp[4]; if (dsk < disk_nr) { st_disk_i = st_disk + dsk++; st_disk_i->major = v_major; st_disk_i->minor = v_index; st_disk_i->nr_ios = v_tmp[0]; st_disk_i->rd_sect = v_tmp[2]; st_disk_i->wr_sect = v_tmp[4]; } pos += strcspn(line + pos, " ") + 1; } while (dsk < disk_nr) { /* * Nb of disks has changed, or appending data to an old file * with more disks than are actually available now. */ st_disk_i = st_disk + dsk++; st_disk_i->major = st_disk_i->minor = 0; } } } } fclose(fp);}/* *************************************************************************** * Read stats from /proc/loadavg *************************************************************************** */void read_proc_loadavg(void){ FILE *fp; int load_tmp[3]; if ((fp = fopen(LOADAVG, "r")) != NULL) { /* Read load averages and queue length */ fscanf(fp, "%d.%d %d.%d %d.%d %ld/%d %*d\n", &(load_tmp[0]), &(file_stats.load_avg_1), &(load_tmp[1]), &(file_stats.load_avg_5), &(load_tmp[2]), &(file_stats.load_avg_15), &(file_stats.nr_running), &(file_stats.nr_threads)); fclose(fp); file_stats.load_avg_1 += load_tmp[0] * 100; file_stats.load_avg_5 += load_tmp[1] * 100; file_stats.load_avg_15 += load_tmp[2] * 100; if (file_stats.nr_running) /* Do not take current process into account */ file_stats.nr_running--; }}/* *************************************************************************** * Read stats from /proc/meminfo ***************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -