CMSC216 HW09: Fork, Spoon, and Wait
- Due: 11:59pm Mon 11-Nov-2024 on Gradescope
- Approximately 0.83% of total grade
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()
andwaitpid()
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.