CMSC 421: Principles of Operating Systems

Homework 2: Four Kids and Counting

This homework is due on Monday, Septemeber 28, at 11:59:59 PM (Eastern daylight time). You must use submit to turn in your homework like so: submit cs421_jtang hw2 hw2.c

Your program must be named hw2.c, and it will be compiled on Ubuntu 14.04 as follows:

  gcc --std=c99 -Wall -O2 -o hw2 hw2.c
There must not be any compilation warnings in your submission; warnings will result in grading penalties. In addition, your code must be properly indented and have a file header comment, as described on the coding conventions page.

Due to UMBC policy, you may not use the GL systems for this assignment, because you will be using the fork() system call.

In this homework, you will write a program that spawns multiple child processes. The user will then be able to inspect those processes and attempt to kill them.

Part 1: Create Processes

The C program will be divided into several parts as follows. Begin your program by calling getpid() to obtain its process ID (PID). Display the PID to the screen via printf(); use the %zu specifier when printing the value.

Next, create an unnamed pipe with the pipe() function. Store those file descriptors somewhere.

Third, call fork() four times, to create four (and only four!) child processes. Each child process needs to know which child number it is (one through four); it is up to you to figure out how to do this.

In the parent process, close the reading end of the pipe and then display the PIDs of its child processes.

In the child processes, close the writing end of the pipe. Next, set up a signal handler for SIGUSR1 (see part 5 below). Then within a loop, read from the pipe; this will cause the child processes to block.

Part 2: Main Menu

Within the parent process, display the following menu:

Main Menu:
1. Display children states
2. Kill a child
3. Signal a child
4. Reap a child
5. Kill and reap all children

Read from the user a menu option, and then perform the requested action as below.

Part 3: Display Children States

In the parent process, for each child process, display the child's PID and its process state. To get the process state, open and read from the file /proc/child_pid/stat, where child_pid is the PID of that child process. The state is the third field.

If a child had been reaped successfully (see part 6 below), then do not display its state. Simply display the string "N/A".

Afterwards, return to the main menu.

Process states are represented by various letters. In your code, add a comment block listing all possible letters and what each letter means.

Part 4: Kill a Child

In the parent process, read from the user a number, one through four, representing which child to kill. Write that number to the pipe, then write that number three more times.

When there are multiple readers blocked on a pipe, a single write will only awaken one of those processes. By writing the same string four times, this will ensure that all four child processes get to act upon the command.

These writes will unblock the child processes. Within each child, if the number does not match its identifier, ignore the request. Call sleep(1) and then try read from the pipe again (causing the process to block). This will ensure that all child processes get to act upon the command.

Within the matching child, call exit() to terminate that process.

Part 5: Signal a Child

In the parent process, read from the user a number, one through four, representing which child to signal. Next, send the SIGUSR1 signal to that child process (and only that child).

In the child process, in its signal handler for SIGUSR1, display a message that it received a signal. Next, call exit() to terminate that process.

Afterwards, in the parent process, return to the main menu.

Part 6: Reap a Child

In the parent process, read from the user a number, one through four, representing which child to reap. Then call waitpid() with that child's PID and using the WNOHANG flag. If the return value indicates success, then display a message that the child has been reaped. Otherwise, display a message that the child was not reaped; this would occur if that child has not terminated or had earlier been reaped.

Afterwards, in the main process, return to the main menu.

Part 7: Kill and Reap All Children

In the parent process, for each child that is still alive, send it a kill message (as per part 4). Then sleep() for a second, then reap it (as per part 6). Repeat for all other children that were alive. Finally, quit the program.

It is necessary to kill and reap child processes to avoid creating orphans. In your code, add a comment block describing the consequences of having orphans on your system.

Other Hints and Notes

Extra Credit

Sorry, there is no extra credit available for this assignment.