152 lines
3.7 KiB
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;
|
|
} |