From 548d91460f3e3a784afd72b74ea11e475e21d5c8 Mon Sep 17 00:00:00 2001 From: Amber Date: Sun, 21 Feb 2021 21:21:39 -0500 Subject: [PATCH] Initial commit. --- extra-credit.c | 202 +++++++++++++++++++++++++++++++++++++++ programming-assignment.c | 152 +++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 extra-credit.c create mode 100644 programming-assignment.c diff --git a/extra-credit.c b/extra-credit.c new file mode 100644 index 0000000..387a910 --- /dev/null +++ b/extra-credit.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include + +/************************************************************************** + * Authors: Gary Fleming, Amber McCloughan + * Class: CIS452 - Operating Systems Concepts + * Professor: Dr. Greg Wolffe + * Date: 2/07/2019 + * + * Program that forks off two child processes and waits for them to send + * back signals. If the parent receives a signal, the handler for that + * signal tells them what to do. Uses POSIX signal handling instead of + * ANSI signal handling. + * + * To end the program, do a Ctrl + C. +***************************************************************************/ + +// See comment above function definition. +void sigHandler(int, siginfo_t*, void*); + +/** + * Main function for the program. + */ +int main() +{ + // Structs for sigaction. + struct sigaction actionUsr1, actionUsr2, actionInt; + + // Forked PID and amount of time the child will wait. + int pid, sig, waitTime; + + // Forking off the first child. + pid = fork(); + + // Error handling. + if (pid < 0) + { + fprintf(stderr, "ERROR with fork.\n"); + exit(1); + // Child process code. + } + else if (!pid) + { + // Seeding rand(). + srand(time(NULL) + 1); + + // Loop for sending SIGUSR1. + while (1) + { + // Getting random seconds. + waitTime = (rand() % 5) + 1; + + sig = (rand() % 2) + 1; + + // Waiting for random seconds. + sleep(waitTime); + + if (sig == 1) + { + kill(getppid(), SIGUSR1); + } + else + { + kill(getppid(), SIGUSR2); + } + } + } + + // Saying which process was forked first. + printf("Spawned child PID %d.\n", pid); + + // Forking off a second child. + pid = fork(); + + // Error handling. + if (pid < 0) + { + fprintf(stderr, "ERROR with fork.\n"); + exit(1); + // Child process code. + } + else if (!pid) + { + // Seeding rand(). + srand(time(NULL) + 2); + + while (1) + { + // Getting random seconds. + waitTime = (rand() % 5) + 1; + + sig = (rand() % 2) + 1; + + // Sleeping for random seconds. + sleep(waitTime); + + if (sig == 1) + { + kill(getppid(), SIGUSR1); + } + else + { + kill(getppid(), SIGUSR2); + } + } + } + + // Saying which child forked second. + printf("Spawned child PID %d.\n", pid); + + // Set all bytes to 0. + memset(&actionUsr1, 0, sizeof(struct sigaction)); + memset(&actionUsr2, 0, sizeof(struct sigaction)); + memset(&actionInt, 0, sizeof(struct sigaction)); + + /* + * If SA_SIGINFO is specified in sa_flags, then + * sa_sigaction (instead of sa_handler) specifies + * the signal-handling function for signum. + * (From the man page for sigaction.) + */ + actionUsr1.sa_flags = SA_SIGINFO; + actionUsr2.sa_flags = SA_SIGINFO; + actionInt.sa_flags = SA_SIGINFO; + + // Choosing the signal handlers. + actionUsr1.sa_sigaction = &sigHandler; + actionUsr2.sa_sigaction = &sigHandler; + actionInt.sa_sigaction = &sigHandler; + + /* + * Actually binding the signal handlers. + * I figured out how to do this using the following article: + * https://www.linuxprogrammingblog.com/code-examples/sigaction + */ + sigaction(SIGUSR1, &actionUsr1, NULL); + sigaction(SIGUSR2, &actionUsr2, NULL); + sigaction(SIGINT, &actionInt, NULL); + + // Loop for waiting on signals. + while (1) + { + fprintf(stderr, "Waiting...\n"); + pause(); + } +} + +/** + * Signal handler for all signals. Parameter descriptions pulled + * from the man page for sigaction. + * + * @param sigNum, number of the signal that caused invocation of the + * handler. + * @param siginfo_t*, pointer to a siginfo_t, which is a structure + * containing further information about the signal. + * @param ucontext, pointer to a ucontext_t structure, cast to void*. + * The structure pointed to by this field contains signal + * context information that was saved on the user-space stack by + * the kernel. + */ +void sigHandler(int sigNum, siginfo_t *info, void *ucontext) +{ + // If the signal was SIGUSR1. + if (sigNum == SIGUSR1) + { + // Saying it's SIGUSR1 and telling who sent it. + fprintf(stderr, "Received a SIGUSR1 from PID %d.\n", + info->si_pid); + + // Done handling. + return; + } + // If the signal was SIGUSR2. + else if (sigNum == SIGUSR2) + { + // Saying it's SIGUSR2 and telling who sent it. + fprintf(stderr, "Received a SIGUSR2 from PID %d.\n", + info->si_pid); + + // Done handling. + return; + } + // If the signal was SIGINT (^C). + else if (sigNum == SIGINT) + { + // Goodbye message. + char *message = " received. That's it, " + "I'm shutting you down...\n"; + + // Printing goodbye message. + fprintf(stderr, message); + + // Exiting. + exit(0); + } + + return; +} \ No newline at end of file diff --git a/programming-assignment.c b/programming-assignment.c new file mode 100644 index 0000000..366b050 --- /dev/null +++ b/programming-assignment.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include + +/************************************************************************** + * Authors: Gary Fleming, Amber McCloughan + * Class: CIS452 - Operating Systems Concepts + * Professor: Dr. Greg Wolffe + * Date: 2/07/2019 + * + * Program that forks off a child process and waits for it to send + * signals back. If the parent process receives a signal from the + * child, the signal handler tells the parent what to do. + * + * To end the program, do a Ctrl + C. +***************************************************************************/ + +// See comment above function definition. +void sigHandler(int); + +/** + * Main function of program. + */ +int main() +{ + // Seeding rand(). + srand(time(NULL)); + + /* + * PID from fork, user signal number, + * and time to wait respectively. + */ + int pid, sig, waitTime; + + // Forking off child process. + pid = fork(); + + // Error handling. + if (pid < 0) + { + fprintf(stderr, "ERROR with fork.\n"); + exit(1); + // Child process code. + } + else if (!pid) + { + while (1) + { + /* + * Wait for random amount of time + * between 1 and 5 seconds. + */ + waitTime = (rand() % 5) + 1; + + // Sleep for random time. + sleep(waitTime); + + /* + * Randomly choose between SIGUSR1 + * and SIGUS2. + */ + sig = (rand() % 2) + 1; + + // SIGUSR1 + if (sig == 1) + { + // Send the signal! + kill(getppid(), SIGUSR1); + } + // SIGUSR2 + else + { + // Send the signal! + kill(getppid(), SIGUSR2); + } + } + } + + // Saying which process was forked off. + printf("Spawned child PID %d.\n", pid); + + // Binding signal handlers. + signal(SIGUSR1, sigHandler); + signal(SIGUSR2, sigHandler); + signal(SIGINT, sigHandler); + + // Loop for waiting on signals. + while (1) + { + printf("Waiting...\n"); + pause(); + } + + return 0; +} + +/** + * Handler for signals. Binded for all three signals + * concerned in this application: SIGUSR1 (user-defined + * signal 1), SIGUSR2 (user-defined signal 2), and + * SIGINT (keyboard interrupt signal ^C). Depending + * on which signal is being handled (specified by + * sigNum), the handler will do different things. + * This is driven by the if-else statement. + * + * @param sigNum, the identifying number of the signal + * sent and now being handled. According to the + * man page for signal: + * SIGINT = 2 + * SIGUSR1 = 30, 10, 16 + * SIGUS2 = 31, 12, 17 + */ +void sigHandler(int sigNum) +{ + // If we're dealing with SIGUSR1. + if (sigNum == SIGUSR1) + { + // Saying it's SIGUSR1. + printf("Received a SIGUSR1 signal.\n"); + + // Binding signal handler again. + signal(SIGUSR1, sigHandler); + + // Done handling. + return; + // If we're dealing with SIGUS2. + } + else if (sigNum == SIGUSR2) + { + // Saying it's SIGUSR2. + printf("Received a SIGUSR2 signal.\n"); + + // Binding signal handler again. + signal(SIGUSR2, sigHandler); + + // Done handling. + return; + // If we're dealing with SIGINT (^C). + } + else if (sigNum == SIGINT) + { + // Exit message. + printf(" received. That's it, I'm shutting you down...\n"); + + // Exiting. + exit(0); + } + + return; +} \ No newline at end of file