Initial commit.
This commit is contained in:
commit
56a368dbd1
|
@ -0,0 +1,244 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
/**************************************************************************
|
||||
* Authors: Gary Fleming, Amber McCloughan
|
||||
* Class: CIS452 - Operating Systems Concepts
|
||||
* Professor: Dr. Greg Wolffe
|
||||
* Date: 2/20/2019
|
||||
*
|
||||
* Program that reads to a shared memory segment. A reader process can have
|
||||
* an ID of either 0 or 1. This is determined through program arguments. The
|
||||
* readers wait for a writer to write something, print it, and then allow
|
||||
* the writer to write again.
|
||||
*
|
||||
* The reader relies on the writer to create the shared memory segments.
|
||||
* If the reader goes to get a shared memory segment and it hasn't been
|
||||
* created, the program will end, asking the user to run the writer first.
|
||||
*
|
||||
* We keep track of which reader IDs are actually active using a flag
|
||||
* array called "counter". If counter[0] is 0, no reader with ID 0 is up.
|
||||
* Therefore, the writer process does not have to wait on that reader.
|
||||
*
|
||||
* The flag array "flag" determines synchronization. The writer
|
||||
* must go, and then the readers. The writer cannot write to the shared
|
||||
* memory segment if the readers are still reading. If flag[0] is 1, then
|
||||
* the reader with ID 0 is still reading. The writer waits for both reader
|
||||
* processes to set their flag element to 0 before it writes anything.
|
||||
*
|
||||
* To end the program, do a Ctrl + C.
|
||||
***************************************************************************/
|
||||
|
||||
// Max number of characters to read.
|
||||
#define MAX_CHARS 1024
|
||||
|
||||
// See function implementation for more details.
|
||||
void sigHandler(int);
|
||||
|
||||
// The ID of this reader. Either 0 or 1, depending on argv.
|
||||
int myId;
|
||||
|
||||
// IDs for shared memory.
|
||||
int bufId, flagId, counterId;
|
||||
|
||||
// Shared memory buffer.
|
||||
char *bufPtr;
|
||||
|
||||
// Shared memory flags.
|
||||
int *flagPtr;
|
||||
|
||||
// Shared memory for reader IDs.
|
||||
int *counterPtr;
|
||||
|
||||
// Local buffer.
|
||||
char *localBuf;
|
||||
|
||||
/**
|
||||
* Main function of the reader program. Takes in
|
||||
* an argument, which is the ID of the reader.
|
||||
* This can be either 0 or 1.
|
||||
*
|
||||
* @param argc, number of arguments.
|
||||
* @param argv, the actual arguments.
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Ensuring ID argument exists.
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Please provide either a 0 or 1 as an argument for ID.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Binding signal handler for keyboard interrupt.
|
||||
signal(SIGINT, sigHandler);
|
||||
|
||||
// Initializing the local buffer.
|
||||
localBuf = malloc(sizeof(char) * MAX_CHARS);
|
||||
|
||||
// Determining shared memory keys.
|
||||
key_t bufKey = ftok("Writer.c", 10);
|
||||
key_t flagKey = ftok("Writer.c", 20);
|
||||
key_t counterKey = ftok("Writer.c", 30);
|
||||
|
||||
// Getting shared memory.
|
||||
if ((bufId = shmget(bufKey, sizeof(char) * MAX_CHARS, S_IRUSR | S_IWUSR)) < 0)
|
||||
{
|
||||
perror("Shared memory get failed for buffer... Did the writer create it?\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((flagId = shmget(flagKey, sizeof(int) * 2, S_IRUSR | S_IWUSR)) < 0)
|
||||
{
|
||||
perror("Shared memory get failed for flag... Did the writer create it?\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((counterId = shmget(counterKey, sizeof(int) * 2, S_IRUSR | S_IWUSR)) < 0)
|
||||
{
|
||||
perror("Shared memory get failed for the counter... Did the writer create it?\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Attaching shared memory.
|
||||
if ((bufPtr = shmat(bufId, 0, 0)) == (void *)-1)
|
||||
{
|
||||
perror("Couldn't attach buffer pointer...\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((flagPtr = shmat(flagId, 0, 0)) == (void *)-1)
|
||||
{
|
||||
perror("Couldn't attach flag pointer...\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((counterPtr = shmat(counterId, 0, 0)) == (void *)-1)
|
||||
{
|
||||
perror("Couldn't attach counter pointer...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Determining ID based on arguments.
|
||||
if (atoi(argv[1]) == 0)
|
||||
{
|
||||
if (counterPtr[0] == 1)
|
||||
{
|
||||
printf("Reader with ID 0 already exists. Please use the other ID.\n");
|
||||
|
||||
// Detaching shared memory segments.
|
||||
if (shmdt(bufPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach buffer memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(flagPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach flag memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(counterPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach counter memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
myId = 0;
|
||||
counterPtr[0] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (counterPtr[1] == 1)
|
||||
{
|
||||
printf("Reader with ID 1 already exists. Please use the other ID.\n");
|
||||
|
||||
// Detaching shared memory segments.
|
||||
if (shmdt(bufPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach buffer memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(flagPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach flag memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(counterPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach counter memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
myId = 1;
|
||||
counterPtr[1] = 1;
|
||||
}
|
||||
|
||||
// Reading loop.
|
||||
while (1)
|
||||
{
|
||||
// Wait until writer writes something.
|
||||
while (flagPtr[myId] != 1)
|
||||
;
|
||||
|
||||
// Reading from buffer.
|
||||
strcpy(localBuf, bufPtr);
|
||||
|
||||
// I'm done with my critical section.
|
||||
flagPtr[myId] = 0;
|
||||
|
||||
// Print out what the writer wrote.
|
||||
printf("%s\n", localBuf);
|
||||
}
|
||||
|
||||
// Exit.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
|
||||
// Turning off different flags.
|
||||
counterPtr[myId] = 0;
|
||||
flagPtr[myId] = 0;
|
||||
|
||||
// Freeing local buffer.
|
||||
free(localBuf);
|
||||
|
||||
// Detaching shared memory segments.
|
||||
if (shmdt(bufPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach buffer memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(flagPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach flag memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(counterPtr) < 0)
|
||||
{
|
||||
perror("Couldn't detach counter memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Exiting program.
|
||||
exit(0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
/**************************************************************************
|
||||
* Authors: Gary Fleming, Amber McCloughan
|
||||
* Class: CIS452 - Operating Systems Concepts
|
||||
* Professor: Dr. Greg Wolffe
|
||||
* Date: 2/21/2019
|
||||
*
|
||||
* Program that writes to a shared memory segment. In charge of creating
|
||||
* the segments and reading user input into them. Can only write if both
|
||||
* readers are not reading (lockstep synchronization).
|
||||
*
|
||||
* We keep track of which reader IDs are actually active using a flag
|
||||
* array called "counter". If counter[0] is 0, no reader with ID 0 is up.
|
||||
* Therefore, the writer process does not have to wait on that reader.
|
||||
*
|
||||
* The flag array "flag" determines synchronization. The writer
|
||||
* must go, and then the readers. The writer cannot write to the shared
|
||||
* memory segment if the readers are still reading. If flag[0] is 1, then
|
||||
* the reader with ID 0 is still reading. The writer waits for both reader
|
||||
* processes to set their flag element to 0 before it writes anything.
|
||||
*
|
||||
* To end the program, do a Ctrl + C.
|
||||
***************************************************************************/
|
||||
|
||||
// Max number of characters to be read.
|
||||
#define MAX_CHARS 1024
|
||||
|
||||
// See function implementation for details.
|
||||
void sigHandler(int);
|
||||
|
||||
// Shared memory IDs.
|
||||
int bufId, flagId, counterId;
|
||||
|
||||
// Shared memory segment for buffer.
|
||||
char *bufPtr;
|
||||
|
||||
// Shared memory segment for flags.
|
||||
int *flagPtr;
|
||||
|
||||
// Shared memory segment for reader IDs.
|
||||
int *counterPtr;
|
||||
|
||||
// Local buffer for user input.
|
||||
char *localBuf;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Binding signal handler for keyboard interrupt.
|
||||
signal(SIGINT, sigHandler);
|
||||
|
||||
// Initializing local buffer.
|
||||
localBuf = malloc(sizeof(char) * MAX_CHARS);
|
||||
|
||||
// Determining shared memory keys.
|
||||
key_t bufKey = ftok("Writer.c", 10);
|
||||
key_t flagKey = ftok("Writer.c", 20);
|
||||
key_t counterKey = ftok("Writer.c", 30);
|
||||
|
||||
// Creating shared memory segments.
|
||||
if ((bufId = shmget(bufKey, sizeof(char) * MAX_CHARS, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) < 0)
|
||||
{
|
||||
perror("Shared memory get failed... Are processes from a previous session still running?\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((flagId = shmget(flagKey, sizeof(int) * 2, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) < 0)
|
||||
{
|
||||
perror("Shared memory get failed... Are processes from a previous session still running?\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((counterId = shmget(counterKey, sizeof(int) * 2, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) < 0)
|
||||
{
|
||||
perror("Shared memory get failed... Are processes from a previous session still running?\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Attaching shared memory segments.
|
||||
if ((bufPtr = shmat(bufId, 0, 0)) == (void *)-1)
|
||||
{
|
||||
perror("can't attach\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((flagPtr = shmat(flagId, 0, 0)) == (void *)-1)
|
||||
{
|
||||
perror("can't attach\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((counterPtr = shmat(counterId, 0, 0)) == (void *)-1)
|
||||
{
|
||||
perror("can't attach\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Writing loop.
|
||||
while (1)
|
||||
{
|
||||
// Reading from user input.
|
||||
fgets(localBuf, MAX_CHARS, stdin);
|
||||
|
||||
// Removing newline character from input.
|
||||
strtok(localBuf, "\n");
|
||||
|
||||
// Waiting on any readers to finish up before writing.
|
||||
while (flagPtr[0] != 0 || flagPtr[1] != 0)
|
||||
;
|
||||
|
||||
// Writing local buffer into shared memory.
|
||||
strcpy(bufPtr, localBuf);
|
||||
|
||||
/*
|
||||
* Readers, you may read now. If a reader at a given ID
|
||||
* does not exist, we don't set their flag to 1. This
|
||||
* is why we used counterPtr, which keeps track of if
|
||||
* a reader is active at a given ID. This allows for 1
|
||||
* writer and 1 reader if you desire.
|
||||
*/
|
||||
flagPtr[0] = counterPtr[0];
|
||||
flagPtr[1] = counterPtr[1];
|
||||
}
|
||||
|
||||
// Exit.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
|
||||
// Freeing local buffer.
|
||||
free(localBuf);
|
||||
|
||||
// Flagging shared memory segments for deletion.
|
||||
if (shmctl(bufId, IPC_RMID, 0) < 0)
|
||||
{
|
||||
perror("can't deallocate #1\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmctl(flagId, IPC_RMID, 0) < 0)
|
||||
{
|
||||
perror("can't deallocate #2\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmctl(counterId, IPC_RMID, 0) < 0)
|
||||
{
|
||||
perror("can't deallocate #3\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Detaching shared memory segments.
|
||||
if (shmdt(bufPtr) < 0)
|
||||
{
|
||||
perror("just can't let go #1\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(flagPtr) < 0)
|
||||
{
|
||||
perror("just can't let go #2\n");
|
||||
exit(1);
|
||||
}
|
||||
if (shmdt(counterPtr) < 0)
|
||||
{
|
||||
perror("just can't let go #3\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Exiting program.
|
||||
exit(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue