Answered step by step
Verified Expert Solution
Question
1 Approved Answer
SKEL A3.C /********************************************** * * * IPC One parent process NPROC children * * * * To compile: * * gcc -g -o skel_a3 skel_a3.c
SKEL A3.C
/********************************************** * * * IPC One parent process NPROC children * * * * To compile: * * gcc -g -o skel_a3 skel_a3.c * * * **********************************************/ #include#include #include #include #include #define NPROC (2) /* number of children processes */ #define TRUE 1 #define FALSE 0 #define MARKED 1 /* lock reserved (lock is taken by a child) */ #define NOTMARKED 0 /* lock available (no child process owns this lock) */ #define MAXCHILDLOCKS 4 /* max resource a child can hold before requesting 'release locks' from the LockManager */ #define NO_DEADLOCK 0 /* there is no deadlock */ #define DEADLOCK_DETECTED 1 /* Deadlock detected */ #define MAXLOCKS 10 /* Total available resources (size of the lock table) */ /* * Children send this message to request a lock. */ #define LOCK 100 /* Child requests to lock a resource */ #define RELEASE 200 /* Child requests to release all its resources */ struct msg_requestLock { int lockID; /* this a number from 0 up to (MAXLOCKS-1) */ int Action; /* LOCK, RELEASE */ }; /* * LockManager sends status of request to children */ #define GRANTED 0 #define NOT_GRANTED 1 #define YOU_OWN_IT 2 #define PREVENT 3 struct msg_LockStatus { int status; int by_child; /* if not granded, who owns it */ }; /* * Structure the LockManager holds (this is a single lock) */ struct lock { int marked; int by_child; }; /* * 'lock' holds all the resources */ struct lock locks[MAXLOCKS]; /* MAXLOCKS locks for the manager */ int deadlock = NO_DEADLOCK; /* When deadlock occurs, exit */ int pid [NPROC]; /* Process ids */ /* * Called at the end to cleanup */ void finish() { int i; for(i = 0; i = MAXCHILDLOCKS ) { /* * Child sends request to release all its locks */ printf("\tChild %d: Requesting RELEASE locks. ", pid); fflush(stdout); MSG.Action=RELEASE; write(req,(char *) &MSG,sizeof(struct msg_requestLock)); count = 0; sleep(1); } } /* for(;;) */ } /* child */ int CheckForDeadLock() { return(NO_DEADLOCK); } /******************************************************* * * * LockManager(): * * Task to determine deadlock * * Also to release and give locks * * Terminates when LiveLock is detected * *******************************************************/ int LockManager( int q, struct msg_requestLock ChildRequest, int respond[NPROC] ) { int i; struct msg_LockStatus STAT; int deadlock=NO_DEADLOCK; if( ChildRequest.Action == RELEASE ) { /* * ***TODO*** (1) * Release child's resources. * Give resources to children that might be waiting * for these resources. */ } if( ChildRequest.Action == LOCK ) { int t_lock; t_lock = ChildRequest.lockID; if( locks[t_lock].marked == NOTMARKED ) { /* * ***TODO*** (2) * Give requested lock to child */ } else { /* lock is not free */ if( locks[t_lock].by_child == q ) { /* * Tell child that this lock is already owned * by this (the requestor) child */ STAT.status=YOU_OWN_IT; write(respond[q], (char *) &STAT, sizeof(STAT)); } else { /* lock taken by another child */ /* * ***TODO*** (3) * Lock is owned by another child, need to wait! * Set up the waiting list. */ /* * Now tell the child that the Lock will * not be given (because it's owned by * someone else. */ STAT.status=NOT_GRANTED; STAT.by_child = locks[t_lock].by_child; write(respond[q], (char *) &STAT, sizeof(STAT)); /* * ***TODO*** (4) * Print the lock table and the waiting list * so that YOU see what your program is doing */ /* * ***TODO*** (5) * Implement the 'CheckForDeadLock()' * function. If you see a deadlock return * DEADLOCK_DETECTED as shown below. */ if( CheckForDeadLock() == DEADLOCK_DETECTED ) { printf("NOW ROLLBACK "); /* * ***TODO*** (6) * Detected Deadlock! you need to * prevent it. Rollback so that ` * you will not give the lock to * the requestor. */ /* * OK we rolledback, now notify the * child that the lock will not be * given to it in order to prevent * the deadlock. */ STAT.status=PREVENT; write(respond[q], (char *) &STAT, sizeof(STAT)); /* * ***TODO*** (7) * Now that we prevented the deadlock * check to see if there are any free * locks. If not, we will be * preventing deadlocks for ever. * If there are no more free * locks/resources then we got a * LiveLock and we should * 1. Print a message on the screen * 2. Print the lock table and the * waiting list/graph. * 3. Terminate. */ } } } } // // if ChildRequest.Action is neither RELEASE nor LOCK, you got a protocol error. // return(deadlock); } /****************************************************************** * ******************************************************************/ int main(int argc, char** argv) { int i; int listen[NPROC]; int respond[NPROC]; int ii; struct msg_requestLock ChildRequest; /* * Arrange for termination to call the cleanup procedure */ signal( SIGTERM, finish ); /* * initialize, don't carre about child */ for( ii = 0; ii parent pipe. */ pipe(child_to_parent); listen[i] = child_to_parent[0]; fcntl (listen[i], F_SETFL, O_NONBLOCK); /* * Create the parent -> child pipe. */ pipe(parent_to_child); respond[i] = parent_to_child[1]; fcntl (respond[i], F_SETFL, O_NONBLOCK); /* * Create child process. */ if ((pid[i] = fork()) == 0) { /* * *********** Child process code. *********** */ signal (SIGTERM, SIG_DFL); close (parent_to_child[1]); close (child_to_parent[0]); child (i, child_to_parent[1], parent_to_child[0]); _exit(0); } close (child_to_parent[1]); close (parent_to_child[0]); } /* * For this assignment there will never be a deadlock because our * LockManager prevents deadlocks */ while( deadlock != DEADLOCK_DETECTED ) { int q; for( q = 0; q
Deadlocks and IPC In this assignment you will learn how to program using fork0, pipe0, write0, read0 to communicate between a parent process and multiple children processes t process and multiple children processes The assignment is to complete the LockManager) that allocates and releases resources to other processes. The LockManager's responsibility is to also detect AND prevent deadlocks. In addition, it must also detect livelocks. When a livelock is detected, the program must terminate. A skeleton program skel a3.c is given. To compile it type: gcc -g -o skel_a3 skel_a3.c If you prefer the C++ compiler download skel a3.cpp program. To compile it type: gtt -o skel_a3 skel_a3.cpp The main0 function creates the pipes and forks NPROC number of children processes. read0s on the parent process are non-blocking, where readOs on the children processes are blocking The sections that contain ***TODO***need to be implemented by you. Comments in the source code explain what needs to be done in more detail For some additional notes see this link
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started