CMSC 421: Principles of Operating Systems

Homework 2: It's a Great Day for Hockey

This homework is due on Tuesday, February 28, at 11:59:59 PM (Eastern standard time). You must use submit to turn in your homework like so: submit cs421_jtang hw2 team.c player.c

Your programs must be named team.c and player.c, and they will be compiled on Ubuntu 16.04 as follow:

  gcc ‐‐std=c99 ‐Wall ‐O2 ‐o team team.c
  gcc ‐std=c99 ‐Wall ‐O2 ‐o player player.c
(Note the above is dash, dash, "std=c99", and the other flags likewise are preceded by dashes.) There must not be any compilation warnings in your submission; warnings will result in grading penalties. In addition, each code file 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 be simulating part of an ice hockey game. In hockey, the five positional players and their abbreviations are:

In this assignment, your code will simulate passing a puck between the players, One of those players will be designated as the goal scorer; when that player receives the puck then a goal is scored.

The first file, team.c, is the main driver for this assignment, and it is responsible for handling the user interface. At startup, it spawns multiple players, each represented as instances of player.c. The driver then sends a POSIX signal to one of the processes, to simulate the puck pass.

Part 1: Create Processes

The team.c program will be divided into several parts as follows. When the process begin, inspect its command line arguments. There must be exactly one arguments (plus the program name itself); if not then display an error message and quit. This argument identifies the designated goal scorer. It will be one of C, LW, RW, D, or D2, case-sensitive.

Second, create five unnamed pipes. Each pipe will be associated with a player (first pipe to C, second pipe to LW, and so forth). Next, call fork() five times, to create five child processes. The first child process will be C, second process will be LW, third is RW, fourth is D, and fifth is D2. Store the child processes' PIDs somewhere convenient.

In each child process, after the fork(), ensure the child process does not continue forking additional processes! Call dup2() to both close stdin and duplicate the reading end of the pipe associated with that child process. Next, close all pipes' file descriptor, for a total of 10 closes. The pipe associated with the process can still be read via the file descriptor that now occupies stdin. Third, call execlp() to execute the player program. While executing the program, pass two command line arguments:

  1. That process's position (C, LW, RW, D, or D2).
  2. The designated goal scorer, from when team was invoked.

In player, display its PID and its position. Use the %ld specifier when printing the PID. Next, set up signal handlers for the signals SIGUSR1 and SIGUSR2. Initialize a global variable to zero; this number will hold the number of times that player has handled the puck. Then read from stdin (which is really its unnamed pipe); this will cause the child process to block.

Back in the parent process, after it has spawned the five child processes, close the reading end of all five pipes. Then write something to all five pipes, to indicate that all child processes have been created. (The data written are irrelevant.)

Because player was reading from the pipe, it will be unblocked. It is now responsible for finding the PIDs of the other members of the hockey team. Read from /proc/sys/kernel/pid_max; this is the maximum PID for your system. Then try reading from the file /proc/X/cmdline, where X ranges from 1 up to the maximum PID. If the file can be read and it contains the name of the player process, then store the PID for Part 3 below. During this search, skip its own PID. Afterwards, the process should have discovered the four PIDs of its sibling processes. Now, initialize the pseudo-random number generator. Do this by calling srand(), passing its own PID as the sole argument. Finally, enter a loop that continuously tries to read from the stdin again; this will cause the process to block again.

Part 2: Main Menu

Within the parent process, in team, display the following menu:

Main Menu:
0. Pass puck to player
1. Show player statistics
2. End game

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

Part 3: Pass Puck to Player

In the parent process, in team, display a submenu of the five positions. Read from the user which position to pass the puck. For the chosen player, send a SIGUSR1 signal to the requested player process.

In the child process, in player, in its signal handler for SIGUSR1, print a message stating that it received the puck. Increment by one the number of times that player has handled the puck. If that process is the designated goal scorer (from when team was invoked), then print a message saying it scored a goal and do nothing more. Otherwise, randomly pick another player (via rand()). Send a SIGUSR1 signal to that process.

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

Part 4: Show Player Statistics

In the parent process, in team, display a submenu of the five positions. Read from the user which position to pass the puck. For the chosen player, send a SIGUSR2 signal to the requested player process.

In the child process, in player, in its signal handler for SIGUSR2, print a message stating its position and how many times it has handled the puck (i.e., the number of SIGUSR1 signals it received).

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

Part 5: End Game

In the parent process, in team, close all five unnamed pipes. Then use waitpid() to wait for each child process to terminate. After all children have ended, end the program.

Because player was reading from the pipe, it will be unblocked. Upon detecting that the pipe was closed, the process terminates itself.

Part 6: Required Documentation

For this assignment, you are required to provide the following documentation. In your team.c file, add a comment block near the top that answers the following questions:

Question 1: Back in Part 3, players could indefinitely pass the puck between themselves without ever sending it to the designated goal scorer. As currently described, there is no way for team to know when the goal was scored. Describe how you would modify your program files so that team will wait for the goal to be scored, prior to returning to the main menu. Do not actually write the code; just describe how using pseudocode.

Question 2: Research Linux's virtual file /proc/X/stat. List all of the possible process states and their one letter abbreviations. Then identify which state(s) a player process is in when it is blocked against the pipe, and then which state(s) it is in while executing a signal handler.

Sample Output

Here is a sample output from running team. The parts that are bolded are outputs from player processes. Observe that because multiple processes are trying to write to the terminal simultaneously, their outputs are interleaved in non-obvious ways.

Main Menu:
0. Pass puck to player
1. Show player statistics
2. End game
Choose an option> C has pid 6825
LW has pid 6826
D2 has pid 6829
D has pid 6828
RW has pid 6827
(User enters 0.)
0. C
1. LW
2. RW
3. D
4. D2
Choose a player> 0
Main Menu:
0. Pass puck to player
1. Show player statistics
2. End game
Choose an option> C got the puck.
RW got the puck.
LW got the puck.
(User enters 0.)
0. C
1. LW
2. RW
3. D
4. D2
Choose a player> (User enters 4.)
Main Menu:
0. Pass puck to player
1. Show player statistics
2. End game
Choose an option> D2 got the puck.
D got the puck.
RW got the puck.
LW got the puck.
(User enters 1.)
0. C
1. LW
2. RW
3. D
4. D2
Choose a player> (User enters 2.)
Main Menu:
0. Pass puck to player
1. Show player statistics
2. End game
Choose an option> RW touched the puck 2 time(s).
(User enters 2.)

Other Hints and Notes

Extra Credit

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