Last Updated: 2024-11-03 Sun 22:37

CMSC216 HW09: Fork, Spoon, and Wait

CODE DISTRIBUTION: hw09-code.zip

  • Download the code distribution every HW
  • See further setup instructions below

CHANGELOG: Empty

1 Rationale

Processes are created in Unix by fork()'ing an existing process so mastery of these system calls is essential to bringing new running programs into the system. Processes created in this way are the children of the creating parent process which can detect changes in their state using the wait() family of calls. Many programming paradigms rely on the parent tracking its children necessitating an understanding of the wait() family. Children execute the same code code as parents unless a call to a member of the exec() family is made which replaces a running child's instructions with a different program. After creating child processes with the fork() call, a parent is obliged to wait for them at some point but the waitpid() provides capabilities such as non-blocking (non-hanging) waits illustrated in this HW. This gives insight into how background shell commands like ./program & may be implemented.

Associated Reading

Ch 8.4 of Bryant/O'Hallaron introduces and shows many examples of fork(), wait(), exec()

Grading Policy

Credit for this HW is earned by taking the associated HW Quiz which is linked under Gradescope. The quiz will ask similar questions as those that are present in the QUESTIONS.txt file and those that complete all answers in QUESTIONS.txt should have no trouble with the quiz.

Homework and Quizzes are open resource/open collaboration. You must submit your own work but you may freely discuss HW topics with other members of the class.

See the full policies in the course syllabus.

2 Codepack

The codepack for the HW contains the following files:

File State Description
QUESTIONS.txt Edit Questions to answer
fork_report.c Edit C file for Problem 1
run_child.c Edit C file for Problem 2
wait_loop.c Edit C file for Problem 3
sleep_print.c Provided Problem 3 program to run in background
exec_fail.c Optional Optional code demoing exec() error checking
    NOTE: No Makefile is provided; use gcc file.c for these simple programs

3 What to Understand

Make sure you get a good understanding of

  • How fork is used to clone a running process to create a child
  • How each process has a unique pid, process ID, available via library calls
  • How wait() and waitpid() can be used to ensure order in execution by causing a parent to wait for a child to finish
  • How execvp() is used to replace a running program with a different program

All of these things will show up in projects.

4 Questions about fork(), wait(), and exec()

                            ________________

                             HW09 QUESTIONS
                            ________________


Write your answers to the questions below directly in this text file to
prepare for the associated quiz. Credit for the HW is earned by
completing the associated online quiz on Gradescope.


PROBLEM 1 `fork_report.c'
=========================

A
~

  Compile and run the program in `fork_report.c'. Run the program
  several times. Show the output of a typical run below.


B
~

  Is the output ordered or disordered with respect to the "I am
  number..." statements? Why?


C
~

  Add calls to the wait() or waitpid() function to ensure that the
  output is ordered. Compile and rerun the code to ensure that your code
  will enforce ordered output. Paste your completed code below.


D
~

  How many parents and children are there in this program? What is their
  arrangement? How are the parent process(es) numbered?


PROBLEM 2 `run_child.c'
=======================

A
~

  Compile and run the program in `run_child.c'. Show it's output below.


B
~

  Adjust the contents of the `child_argv[]' array. Try removing the "-l"
  element, try adding on ".." prior to the final NULL, or make other
  modifications INCLUDING for the 0th "ls" string.  Recompile and
  describe whether the output has changed.


C
~

  Change the child_cmd string from "ls" to be something else like "gcc"
  or "cat". A good combination is "gcc" with the "--version" as the only
  option in the child_argv array. Recompile and explain what happens
  now.


D
~

  Currently `run_child.c' does not reach the bottom statements.
  ,----
  |   printf("------------------\n");
  |   printf("Child Finished\n");
  `----
  Correct this by doing the following:
  - Fork a child process
  - Have ONLY the child process call execvp()
  - Have the parent process wait() for the child
  Paste your completed code below.


PROBLEM 3 `wait_loop.c'
=======================

  Examine the C file `wait_loop.c'. It implements a primitive
  interactive loop asking a user to type things while a child process
  runs in the background. By default, the provided `sleep_print.c'
  program is used which creates a delay before the program
  finishes. Make sure to compile `sleep_print' then compile
  `wait_loop.c' and experiment with its behavior.

  Here is a brief demo.
  ,----
  | >> gcc -o sleep_print sleep_print.c 
  | >> gcc wait_loop.c
  | >> ./a.out
  | Type text then press enter to check on child:
  | input: hello there
  | Entered text: 'hello there'
  | Waiting
  | CHILD: Awake and Done 
  | CHILD FINISHED: 
  | 
  | Type text then press enter to check on child:
  | input: what?
  | Entered text: 'what?'
  | Waiting
  | Child not finished: wait returned -1
  | 
  | Type text then press enter to check on child:
  | input: stop
  | Entered text: 'stop'
  | Waiting
  | Child not finished: wait returned -1
  | 
  | Type text then press enter to check on child:
  | input:  Ctrl-c
  | > 
  `----


A
~

  Alter the code so that when the child has completed execution, the
  program breaks out of the loop and the program ends normally. Paste in
  the code you used for this.


B
~

  Adjust the code so that the exit status of the child process is
  printed when it finishes. Make sure to use the macros
  `WIFEXITED(status)' and `WEXITSTATUS(status)' to deal with the
  `status' set by `waitpid()'.  Paste the code you added for your
  answer.


C
~

  Make changes so that if the user types in the string `quit', the
  program exits immediately without waiting further for the
  child. Example:
  ,----
  | > a.out
  | Type text then press enter to check on child:
  | >> quit
  | Entered text: 'quit'
  | Quitting
  | Exiting wait_loop
  | > CHILD: Awake and Done 
  `----
  Note that the child eventually prints output to the screen which is
  fine.

  You will need to check the user input using either the `strcmp()'
  (unsafe) or `strncmp()' (safer) function. Do some research on this
  function if it is unfamiliar as it will prove generally useful.

  Paste the code you used below.


D
~

  The current call to `waitpid()' blocks, pausing execution of the
  parent process until the child finishes. Look up the option to pass to
  `waitpid()' that will allow it to do a non-blocking wait which returns
  immediately if the child is not finished. A sample behavior is below.
  ,----
  | > a.out
  | Type text then press enter to check on child:
  | >> stuff
  | Entered text: 'stuff'
  | Waiting
  | Child not finished: wait returned 0
  | 
  | Type text then press enter to check on child:
  | >> more stuff
  | Entered text: 'more stuff'
  | Waiting
  | Child not finished: wait returned 0
  | 
  | Type text then press enter to check on child:
  | >> CHILD: Awake and Done 
  | Looks like you're finally up
  | Entered text: 'Looks like you're finally up'
  | Waiting
  | CHILD FINISHED: Exit status 5
  | Exiting wait_loop
  | > 
  `----

  Paste your entire code for `wait_loop.c' below.

Author: Chris Kauffman (profk@umd.edu)
Date: 2024-11-03 Sun 22:37