SICE Curriculum Portal for Thomas Heffron
Contents

Home
UMKC Curriculum
   FS '96
      CS 101
   SS '01
      CS 201
   FS '01
      CS 191
      CS 281
   WS '02
      CS 291
      EN 304wi
   SS '02
      CS 352
      CS 481
   FS '02
      CS 431
      CS 441
   WS '03
      CS 423
      CS 451
SICE Survival Guide
Personal Experience

contact me @umkc:
tehqnf@umkc.edu

CS431 - Homework #2

/******************************************
Name:      Thomas Heffron (tehqnf@umkc.edu)
Section:   CS431 NET
Program:   Program #2
Due Date:  Oct. 1, 2002
Desc:      Write a small program to pull information
           from the /proc directory on a Linux system
Inputs:    No input from user.
           All info is read from /proc directory
Outputs:   Well formatted information about:
                 - machine name
                 - system time
                 - kernel version
                 - memory usage
                 - uptime/idletime before and after a load
*******************************************/

#include <stdio.h>
#include <string.h>
#include <sys/time.h>

int main()
{
    /* Type declarations */
    char hostname[50];
    char kernel[100];
    time_t now;
    unsigned long start_uptime_int = 0, start_idle_int = 0;
    unsigned long end_uptime_int = 0, end_idle_int = 0;
    float start_uptime_frac = 0.0, start_idle_frac = 0.0;
    float end_uptime_frac = 0.0, end_idle_frac = 0.0;
    float idle_percent, total_real_time, total_idle_time;
    char TOTAL_STR[] = "TOTAL";
    char IDLE_STR[] = "IDLE";

    /* Function declarations */
    void get_hostname(char *value);
    void get_kernel_info(char *value);
    void show_memory_info();
    void get_time_stats(unsigned long *up_int,
    float *up_frac,
    unsigned long *id_int, float *id_frac);
    void format_seconds(unsigned long secs, float frac);
    void work(int loops);
    float get_time_diff(unsigned long start_int,
    float start_frac,
    unsigned long end_int, float end_frac);

    /* Start of processing */
    printf("\nHere's some general info on this system:\n");
 
    /* Hostname information */
    get_hostname(hostname);
    printf("Hostname: %s\n", hostname);

    /* System time */
    time(&now);
    printf("System Time: %s", ctime(&now));

    /* Kernel version */
    get_kernel_info(kernel);
    printf("You are working in the %s kernel\n", kernel);

    /* Memory usage */
    show_memory_info();

    /* Load average since LAST REBOOT */
    printf("\nStatistics on busy/idle time:\n");
    get_time_stats(&start_uptime_int,
        &start_uptime_frac, &start_idle_int, &start_idle_frac);
    printf("Uptime: %lu seconds - or ", start_uptime_int);
    format_seconds(start_uptime_int, start_uptime_frac);
    printf("Idle: %lu seconds - or ", start_idle_int);
    format_seconds(start_idle_int, start_idle_frac);
    idle_percent = ((float) start_idle_int /
        (float) start_uptime_int) * 100.0;
    printf("This system has been idle %.2f%c of the time.\n\n",
        idle_percent, '%');

    /********************************
    / Place a load on the CPU
    / !!! Make sure that stats are gathered
    / immediately before and after work
    / is performed.!!!
    / Additional statements may skew data.
    ********************************/
    printf("Let's do some work...\n");
    get_time_stats(&start_uptime_int,
    &start_uptime_frac, &start_idle_int, &start_idle_frac);
    work(5);
    get_time_stats(&end_uptime_int,
        &end_uptime_frac, &end_idle_int, &end_idle_frac);

    /* Calculate elapsed real time */
    total_real_time = get_time_diff(start_uptime_int,
        start_uptime_frac,
        end_uptime_int, end_uptime_frac);

    /* Calulate elapsed idle time */
    total_idle_time = get_time_diff(start_idle_int,
        start_idle_frac,
        end_idle_int, end_idle_frac);

    /* Finally, display formatted results */
    printf("Done!!!\n\n");
    printf("%20s%15s\n", TOTAL_STR, IDLE_STR);
    printf("Start: %9lu%.2f %9lu%.2f\n", (start_uptime_int / 10),
        ((float) (start_uptime_int % 10) + start_uptime_frac),
        (start_idle_int / 10),
        ((float) (start_idle_int % 10) + start_idle_frac));
    printf("End: %9lu%.2f %9lu%.2f\n", (end_uptime_int / 10),
        ((float) (end_uptime_int % 10) + end_uptime_frac),
        (end_idle_int / 10),
        ((float) (end_idle_int % 10) + end_idle_frac));
    printf("Diff: %13.2f %13.2f\n", total_real_time, total_idle_time);
    printf("That work cycle kept the system busy %4.2f%c of the time.\n",
        (((total_real_time - total_idle_time) / total_real_time) * 100),
        '%');
} /* End of main() */

/* Function to remove all newline chars */
/* from a string (char array) by replacing */
/* it with at blank if not at end of string */
/* or removing it if at the end. */
void remove_crln(char *value)
{
    int str_len, i = 0;

    str_len = strlen(value);
    while (value[i] != '\0') {
        if (value[i] == '\n') {
            if (value[i + 1] == '\0') {
                value[i] = '\0';
            } else {
                value[i] = ' ';
            }
        }
        i++;
    }
}

/* Subroutine to return a float calculated */
/* from the difference in seconds held in the */
/* four different variables as returned from the */
/* get_time_stats function. It will automatically */
/* carry a one from the whole second value */
/* if needed for proper subtraction */
float get_time_diff(unsigned long start_int,
            float start_frac,
            unsigned long end_int, float end_frac)
{
    if ((end_frac - start_frac) < 0.0) {
        return (((1.0 + end_frac) - start_frac) +
            (float) ((end_int - 1) - start_int));
    } else {
        return ((end_frac - start_frac) + (float) (end_int - start_int));
    }
}

/* Subroutine to manipulate the actual variable */
/* passed to a more readable form in less than */
/* three digits as well as returning a char that */
/* represents the magnitude of new value. */
char format_memory(unsigned long *mem_val)
{
    int mem_pow = 0;
    char byte_val;
    unsigned long temp_val;
 
    temp_val = *mem_val;
    while ((temp_val / 1024) > 0) {
        temp_val /= 1024;
        mem_pow += 1;
    }
    *mem_val = temp_val;
    switch (mem_pow) {
        case 0:
            byte_val = 'B';
            break;
        case 1:
            byte_val = 'K';
            break;
        case 2:
            byte_val = 'M';
            break;
        case 3:
            byte_val = 'G';
            break;
    }
    return byte_val;
}

/* Function to display the two parts (whole */
/* and fraction) of a large value seconds */
/* in a more readable form including days, */
/* hours, minutes, and seconds. */
void format_seconds(unsigned long secs, float fracs)
{
    unsigned long temp_sec = secs;
    float temp_frac = fracs;
    int form_sec, form_min, form_hrs, form_day;
 
    form_sec = temp_sec % 60;
    temp_sec /= 60;
    form_min = temp_sec % 60;
    temp_sec /= 60;
    form_hrs = temp_sec % 24;
    temp_sec /= 24;
    form_day = temp_sec;
    temp_frac += form_sec;

    if (temp_frac < 10.0) {
        printf("%03dD %02d:%02d:0%.2f(H:M:S)\n",
            form_day, form_hrs, form_min, temp_frac);
    } else {
        printf("%03dD %02d:%02d:%.2f(H:M:S)\n",
            form_day, form_hrs, form_min, temp_frac);
    }
}

/* Function to gather the values read from */
/* /proc/uptime file. These values are stored */
/* in separate parts as a large integer and */
/* fractional portion. This is necessary because */
/* uptime reports in seconds that will always be */
/* positive and large. A double variable may */
/* cause unwanted rounding. */
void get_time_stats(unsigned long *up_int,
    float *up_frac, unsigned long *id_int, float *id_frac)
{
    FILE *in_file;
    float trash;

    in_file = fopen("/proc/uptime", "r");
    fscanf(in_file, "%lu%f%lu%f",
        &(*up_int), &(*up_frac), &(*id_int), &(*id_frac));

    fclose(in_file);
}

/* Function to display the current memory */
/* in raw form from the /proc/meminfo file */
/* and in a more readable form using the */
/* format_memory() function. Again, unsigned */
/* long integer is used bacause values are */
/* positive, very large, and rounding is not */
/* acceptable. */
void show_memory_info()
{
    FILE *in_file;
    char temp_str[200];
    unsigned long mem_avail, mem_free, mem_used;
    unsigned long kmem_avail, kmem_free, kmem_used;
    int i;
    char avail_unit, free_unit, used_unit;

    in_file = fopen("/proc/meminfo", "r");
    fgets(temp_str, 200, in_file);
    fscanf(in_file, "%s", temp_str);
    fscanf(in_file, "%lu %lu %lu", &mem_avail, &mem_used, &mem_free);

    kmem_avail = mem_avail;
    kmem_used = mem_used;
    kmem_free = mem_free;
 
    avail_unit = format_memory(&kmem_avail);
    free_unit = format_memory(&kmem_free);
    used_unit = format_memory(&kmem_used);

    printf("Mem Used: %10lu (~%3lu%c)\n", mem_used, kmem_used, used_unit);
    printf("Mem Free: %10lu (~%3lu%c)\n", mem_free, kmem_free, free_unit);

    fclose(in_file);
}

/* Function to read the O/S type and */
/* version number in the /proc directory */
/* then storing them in the char array */
/* passed by reference */
void get_kernel_info(char *value)
{
    FILE *in_file1, *in_file2;
    char string_val1[20], string_val2[20];
    int str_len, i = 0;

    in_file1 = fopen("/proc/sys/kernel/ostype", "r");
    fgets(string_val1, 20, in_file1);
    fclose(in_file1);

    in_file2 = fopen("/proc/sys/kernel/osrelease", "r");
    fgets(string_val2, 20, in_file2);
    fclose(in_file2);

    remove_crln(string_val1);
    remove_crln(string_val2);

    strcpy(value, string_val1);
    strcat(value, " ver. ");
    strcat(value, string_val2);
}

/* Function to read the system name */
/* from the /proc/sys/kernel/hostname */
/* file then stored in the char array */
/* passed by reference */
void get_hostname(char *value)
{
    FILE *in_file;
    char string_val1[200];
    int str_len, i = 0;

    in_file = fopen("/proc/sys/kernel/hostname", "r");
    fgets(string_val1, 200, in_file);

    remove_crln(string_val1);
    strcpy(value, string_val1);

    fclose(in_file);
}

/* Function to produce a load on the */
/* system. Iterates number of times */
/* passed into the value loops */
void work(int loops)
{
    double y;
    double x = 3.0;
    double e = 2.0;
    int i, j;
    for (i = 0; i < loops; i++) {
        for (j = 0; j < 400000; j++) {
            y = pow(x, e);
        }
        sleep(1);
    }
}