Initial commit.
This commit is contained in:
commit
9327437424
|
@ -0,0 +1,172 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
/**************************************************************************
|
||||
* Authors: Gary Fleming, Amber McCloughan
|
||||
* Class: CIS452 - Operating Systems Concepts
|
||||
* Professor: Dr. Greg Wolffe
|
||||
* Date: 2/14/2019
|
||||
*
|
||||
* Program that starts out with a dispatcher thread. This thread
|
||||
* waits on user input. When it receives a filename string from
|
||||
* the user, it spawns a worker thread that goes out to
|
||||
* "retrieve" the filename from the "file server". On an exit,
|
||||
* the program prints statistics about files serviced.
|
||||
*
|
||||
* To end the program, do a Ctrl + C.
|
||||
***************************************************************************/
|
||||
|
||||
// Input limit.
|
||||
#define CHAR_LIMIT 1024
|
||||
|
||||
// See function implementations for information.
|
||||
void *file_request(void *arg);
|
||||
void sigHandler(int);
|
||||
|
||||
// File counter.
|
||||
int counter;
|
||||
|
||||
// File access time counter.
|
||||
int timeCounter;
|
||||
|
||||
// Mutex.
|
||||
pthread_mutex_t lock;
|
||||
|
||||
// Input buffer.
|
||||
char *input;
|
||||
|
||||
/**
|
||||
* The main function for driving the program.
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
// Seeding randomness.
|
||||
srand(time(NULL));
|
||||
|
||||
/*
|
||||
* Initializing the mutex.
|
||||
* I figured out how to do this using the following article:
|
||||
* https://www.geeksforgeeks.org/mutex-lock-for-linux-thread-synchronization/
|
||||
*/
|
||||
pthread_mutex_init(&lock, NULL);
|
||||
|
||||
// Thread ID holder.
|
||||
pthread_t thread1;
|
||||
|
||||
// Status variable for checking if pthread_create failed.
|
||||
int status;
|
||||
|
||||
// Initializing file counter.
|
||||
counter = 0;
|
||||
|
||||
// Allocating memory for input buffer.
|
||||
input = malloc(CHAR_LIMIT * sizeof(char));
|
||||
|
||||
// Binding signal handler for keyboard interrupt.
|
||||
signal(SIGINT, sigHandler);
|
||||
|
||||
// The dispatching loop.
|
||||
while (1)
|
||||
{
|
||||
// User input for filename.
|
||||
fprintf(stderr, "Enter file name: ");
|
||||
input = fgets(input, CHAR_LIMIT, stdin);
|
||||
|
||||
// Removing newline character from input.
|
||||
strtok(input, "\n");
|
||||
|
||||
// Spawning a thread to deal with the "file" requested.
|
||||
if ((status = pthread_create(&thread1, NULL, file_request, strdup(input))) != 0)
|
||||
{
|
||||
fprintf(stderr, "Thread creation error %d: %s.\n", status, strerror(status));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function executed by worked threads. Randomly decides
|
||||
* whether the "file" can be accessed from the disk cache
|
||||
* (80% chance) or if it has to be fetched from the hard
|
||||
* drive (20% chance). If the "file" is accessed from cache,
|
||||
* the thread sleeps for a second. If the "file" is accessed
|
||||
* from the hard drive, the thread sleeps for 7-10 seconds.
|
||||
* A mutex is used to ensure mutual exclusion for writes.
|
||||
*
|
||||
* @param arg, the name of the "file" to be handled by the
|
||||
* worker thread.
|
||||
*/
|
||||
void *file_request(void *arg)
|
||||
{
|
||||
// Probability roll for HDD or cache.
|
||||
int val = (rand() % 5) + 1;
|
||||
|
||||
// Variable used for sleep time.
|
||||
int val2;
|
||||
|
||||
// File accessed from disk.
|
||||
if (val == 5)
|
||||
{
|
||||
// 7-10 seconds.
|
||||
val2 = (rand() % 4) + 7;
|
||||
}
|
||||
// File accessed from cache.
|
||||
else
|
||||
{
|
||||
// 1 second.
|
||||
val2 = 1;
|
||||
}
|
||||
|
||||
// Sleep for seconds decided on above.
|
||||
sleep(val2);
|
||||
|
||||
// Serving the file.
|
||||
fprintf(stderr, "\nServing file \"%s\" after %i seconds.\n", (char *)arg, val2);
|
||||
|
||||
// Writing to global variables. Mutex lock!
|
||||
pthread_mutex_lock(&lock);
|
||||
counter++;
|
||||
timeCounter += val2;
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
||||
// Freeing allocated memory.
|
||||
free(arg);
|
||||
|
||||
// Goodbye (no need to return anything).
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for signals. Bound for the one signal handled
|
||||
* in this application: SIGINT (program interrupt signal ^C).
|
||||
*
|
||||
* @param sigNum, the identifying number of the signal
|
||||
* sent and now being handled. According to the
|
||||
* man page for signal, SIGINT = 2.
|
||||
*/
|
||||
void sigHandler(int sigNum)
|
||||
{
|
||||
if (sigNum == SIGINT)
|
||||
{
|
||||
// Exit message.
|
||||
printf(" received. That's it, I'm shutting you down...\n");
|
||||
printf("Files serviced: %i.\n", counter);
|
||||
printf("Avg. file access time: %lf seconds.\n", (double)timeCounter / (double)counter);
|
||||
|
||||
// Destroying mutex.
|
||||
pthread_mutex_destroy(&lock);
|
||||
|
||||
// Freeing user input pointer.
|
||||
free(input);
|
||||
|
||||
// Exiting program.
|
||||
exit(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue