cis-452-lab-6/programming-assignment.c

152 lines
3.7 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/sem.h>
/**************************************************************************
* Authors: Gary Fleming, Amber McCloughan
* Class: CIS452 - Operating Systems Concepts
* Professor: Dr. Greg Wolffe
* Date: 3/14/2019
*
* Program that synchronizes shared memory between two processes.
* Both processes swap memory back and forth, but a semaphore prevents
* them from clobbering data.
*
* You must pass an argument to the program, which is the number of
* times you want each process to swap the memory back and forth.
***************************************************************************/
// Size of shared memory segment.
#define SIZE 16
/**
* Main function of the reader program. Takes in
* an argument, which is the number of times each
* process will loop.
*
* @param argc, number of arguments.
* @param argv, the actual arguments.
*/
int main(int argc, char *argv[])
{
// Status for waiting on the child.
int status;
/* The i for the for loop, the # of times looped, temp variable
for swapping memory, and shared memory pointers.
*/
long int i, loop, temp, *shmPtr;
// Shared memory ID.
int shmId;
// PID for forking.
pid_t pid;
// Getting loop # from program arguments.
loop = atoi(argv[1]); // get value of loop variable (from command-line argument)
// Getting the shared memory segment.
if ((shmId = shmget(IPC_PRIVATE, SIZE, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0)
{
perror("i can't get no..\n");
exit(1);
}
// Attaching shared memory segment.
if ((shmPtr = shmat(shmId, 0, 0)) == (void *)-1)
{
perror("can't attach\n");
exit(1);
}
// Initializing values for shared memory.
shmPtr[0] = 0;
shmPtr[1] = 1;
// Getting semaphore.
int semId = semget(IPC_PRIVATE, 1, 00600);
// Initializing semaphore to 1.
semctl(semId, 0, SETVAL, 1);
// Operation for locking the semaphore (subtract 1)
struct sembuf lock = {0, -1, SEM_UNDO};
// Operating for unlocking the semaphore (add 1)
struct sembuf unlock = {0, 1, SEM_UNDO};
// Forking
if (!(pid = fork()))
{ // Child
for (i = 0; i < loop; i++)
{
// Wait
semop(semId, &lock, 1);
temp = shmPtr[0]; // swap the contents of shmPtr[0] and shmPtr[1]
shmPtr[0] = shmPtr[1];
shmPtr[1] = temp;
// Signal
semop(semId, &unlock, 1);
}
// Detaching shared memory.
if (shmdt(shmPtr) < 0)
{
perror("just can't let go\n");
exit(1);
}
// Child exits.
exit(0);
}
else
{ // Parent
for (i = 0; i < loop; i++)
{
// Wait
semop(semId, &lock, 1);
temp = shmPtr[1]; // swap the contents of shmPtr[1] and shmPtr[0]
shmPtr[1] = shmPtr[0];
shmPtr[0] = temp;
// Signal
semop(semId, &unlock, 1);
}
}
// Waiting on the child to exit.
wait(&status);
// Printing out the values. Should be 0 1.
printf("values: %li\t%li\n", shmPtr[0], shmPtr[1]);
// Detaching shared memory.
if (shmdt(shmPtr) < 0)
{
perror("just can't let go\n");
exit(1);
}
// Flagging shared memory for deletion.
if (shmctl(shmId, IPC_RMID, 0) < 0)
{
perror("can't deallocate\n");
exit(1);
}
// Deleting semaphore.
semctl(semId, 0, IPC_RMID);
// Goodbye.
return 0;
}