Reference no: EM133334746
Systems
Assignment: Purpose:
To practice creating processes and signal handling.
Computing
Please ssh into one of the following:
cdmlsrvprd01.dpu.depaul.edu
or use your own Un*x machine (e.g. Linux or MacOS)
Overview:
We will finish two programs:
caller.c will make NUM_CHILDREN child processes. Each child process will run responder. Then parent process will send either SIGUSR1 or SIGUSR2 a randomly-chosen child. The child will either respond with SIGUSR1 or SIGUSR2. If the parent receives a different signal than it sent then it records that as a "flip". The parent then signals a different child process. It continues doing this for 60 seconds. Then it tells all child processes to stop by sending them SIGTERM. At the end it prints each flip probability of each child, and how many times the child actually did flip its signal.
Each child process runs responder. It is given a probability on its command line. When it is signaled with either SIGUSR1 or SIGUSR2, it sends the other signal to its parent with the given probability. It stops altogether when it receives SIGTERM.
Assignment 1:
/*-------------------------------------------------------------------------*
*--- ---*
*--- caller.c ---*
*--- ---*
*--- This file defines a program that launches child processes ---*
*--- and sends signals to them. ---*
*--- ---*
*--- ---- ---- ---- ---- ----- ---- ---- ---- ---*
*--- ---*
*--- Version 1a Joseph Phillips ---*
*--- ---*
*-------------------------------------------------------------------------*/
/*
* Compile with:
* $ g++ caller.c -o caller
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <wait.h>
const int NUM_CHILDREN = 4;
const int NUM_SECS_TO_RUN = 60;
const int TEXT_LEN = 16;
#define CHILD_PROCESS "responder"
pid_t childPidArray[NUM_CHILDREN];
float probabilityArray[NUM_CHILDREN];
int countArray[NUM_CHILDREN];
int shouldRun = 1;
int lastSignal = SIGUSR1;
// PURPOSE: To respond to SIGALRM by telling the process running this program
// to stop. Ignores 'sigNum'. No return value.
void sigAlarmHandler (int sigNum
)
{
// YOUR CODE HERE
}
// PURPOSE: To send 'sigNum' to the child indexed by 'childIndex'.
// No return value.
void signalChild (int childIndex,
int sigNum
)
{
sleep(1);
printf("Sending %s to %d\n",
((sigNum == SIGUSR1) ? "SIGUSR1" : "SIGUSR2"),
childIndex
);
// YOUR CODE HERE
}
// ONE OR TWO FUNCTIONS HERE
// PURPOSE: To install the signal handler(s). No parameters. No return
// value.
void installSignalHandlers
()
{
struct sigaction act;
// YOUR CODE HERE
}
// PURPOSE: To initialize 'probabilityArray[]' and 'countArray[]'. No
// parameters. No return value.
void initializeProbAndCountArrays
()
{
int index;
for (index = 0; index < NUM_CHILDREN; index++)
{
probabilityArray[index] = ((float)(rand() % 256)) / 256.0;
countArray[index] = 0;
}
}
// PURPOSE: To launch 'NUM_CHILDREN' child processes, each of which runs
// program "responder". No parameters. No return value.
void launchChildren ()
{
int index;
// YOUR CODE HERE
}
// PURPOSE: To send 'SIGTERM' to all 'NUM_CHILDREN' child processes. No
// parameters. No return value.
void tellChildrenToStop
()
{
int index;
for (index = 0; index < NUM_CHILDREN; index++)
{
// YOUR CODE HERE
printf
("Child %d: prob %g, count %d\n",
index,probabilityArray[index],countArray[index]
);
}
}
int main ()
{
// I. Application validity check:
// (Nothing to do)
// II. Run program:
srand(getpid());
// II.A. Install signal handler(s):
installSignalHandlers();
// II.B. Initialize arrays and launch children:
initializeProbAndCountArrays();
launchChildren();
// II.C. Send initial signals:
// YOUR CODE HERE
signalChild(rand() % NUM_CHILDREN,lastSignal);
// II.D. Do the program:
while (shouldRun)
sleep(1);
// II.E. Tell children to stop:
tellChildrenToStop();
// III. Finished:
return(EXIT_SUCCESS);
}
a. sigAlarmHandler()
Change shouldRun so that this program leaves the while loop and main(), and quits.
b. signalChild()
Make this function send signal sigNum to the child indexed by childIndex.
c. Either 1 or 2 functions to handle SIGUSR1 and SIGUSR2
These function(s) must be advanced handlers. It/They must:
Use childPidArray[] to find the index of the child. (Call it childIndex.)
Increment countArray[childIndex] if the signal that was receive was not lastSignal
Do this:
int nextChildIndex;
printf("Received %s from %d\n\n",
((sigNum == SIGUSR1) ? "SIGUSR1" : "SIGUSR2"),
childIndex
);
do
{
nextChildIndex = rand() % NUM_CHILDREN;
}
while (nextChildIndex == childIndex);
lastSignal = theSignalThatWasJustReceived;
signalChild(nextChildIndex,lastSignal);
d. installSignalHandlers()
Installs all signal handlers. Be careful! Some are simple, some are advanced.
e. initializeProbAndCountArrays()
Initializes probabilityArray[] and countArray[]. Already done for you.
f. launchChildren()
Have a loop that makes NUM_CHILDREN child processes and puts their process ids in childPidArray[]. Each child process should run CHILD_PROCESS with the flip probability given as a command line argument. To convert the floating point number to a string, say:
char text[TEXT_LEN];
snprintf(text,TEXT_LEN,"%g",probabilityArray[index]);
g. tellChildrenToStop()
Has a loop that sends SIGTERM to all child processes. (Important! Do not leave any Zombies, now!)
h. main()
Mostly written for you except that you must tell the Operating System to send SIGALRM to you NUM_SECS_TO_RUN seconds in the future.
Assignment 2: responder.c
/*-------------------------------------------------------------------------*
*--- ---*
*--- responder.c ---*
*--- ---*
*--- This file defines a program that responds to SIGUSR1 and ---*
*--- SIGUSR2 from its parents. ---*
*--- ---*
*--- ---- ---- ---- ---- ---- ---- ---- ---- ---*
*--- ---*
*--- Version 1a Joseph Phillips ---*
*--- ---*
*-------------------------------------------------------------------------*/
/*
* Compile with:
* $ gcc responder.c -o responder
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <wait.h>
int shouldRun = 1;
float flipProb = 0.0;
void sigTermHandler (int sigNum
)
{
// YOUR CODE HERE
}
// YOUR CODE HERE
int main (int argc,
char* argv[]
)
{
struct sigaction act;
srand(getpid());
// YOUR CODE HERE
while (shouldRun)
sleep(1);
return(EXIT_SUCCESS);
}
a. sigTermHandler()
Change shouldRun so that this program leaves the while loop and main(), and quits.
b. Write 1 or 2 simple signal handlers to handle SIGUSR1 and SIGUSR2.
Do this:
float thisProb= ((float)(rand() % 256)) / 256.0;
If (flipProb > thisProb) then the signal has flipped. Print "Flipped!\n" and send the opposite signal to the parent process.
If (flipProb <= thisProb) then the signal has not flipped. Print "Same\n" and send the same signal to the parent process.
c. main()
This should do several things:
Make sure that the command line argument for the flip probability is given on the command line. If it is not, then do: fprintf(stderr,"Missing probability argument"); exit(EXIT_FAILURE);
Convert the command line argument from a string into a float, and put its value in flipProb. The value of flipProb should be between [0.0 .. 1.0]. If it is not, then do: fprintf(stderr,"Bad probability argument"); exit(EXIT_FAILURE);
Install all signal handlers.