Lecex 2
Lecex 2
This lecture exercise is due by 11:59PM EDT on Wednesday, June 16, 2021
This lecture exercise consists of practice problems and problems to be handed in for a grade;
graded problems are to be done individually, so do not share your work on graded
problems with anyone else
For all lecture exercise problems, take the time to work through the corresponding video
lecture(s) to practice, learn, and master the material; while the problems posed here are
usually not exceedingly difficult, they are important to understand before attempting to
solve the more extensive homeworks in this course
You must use C for this assignment, and all submitted code must successfully compile
via gcc with no warning messages when the -Wall (i.e., warn all) compiler option is used; we
will also use -Werror, which will treat all warnings as critical errors
All submitted code must successfully compile and run on Submitty, which uses Ubuntu
v18.04.5 LTS and gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04); also note that by
default the gnu11 C standard is used by gcc
Practice problems
Work through the practice problems below, but do not submit solutions to these problems. Feel
free to post questions, comments, and answers in our Discussion Forum.
1. What is the exact output of the fork.c example from the June 7 video lectures if we mod-
ify the code as shown below (i.e., adding printf() statements both before and after we
call fork())?
To best answer this question, revise the diagram shown in the comments after the main()
function.
2. What are the differences between the waitpid() and wait() system calls (covered in the
June 9 video lecture)? What does the return value tell us?
What is the wstatus parameter used for? How many bits are dedicated to each component
encoded in this value?
3. Review the fork-lexec2.c code posted along with this lecture exercise (also shown on the
next page). Assuming no runtime errors occur, determine exactly how many distinct possible
outputs there could be. Show all possible outputs.
/* fork-lexec2.c */
/*
* Lecture Exercise 2 -- Practice Problem 3
*
* How many distinct possible outputs are there?
*
* Show all possible outputs.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int t;
int * q = &t;
t = 19;
pid_t p = fork();
if ( p == 0 )
{
printf( "CHILD: happy birthday to me!\n" );
printf( "CHILD: *q is %d\n", *q );
}
else /* p > 0 */
{
printf( "PARENT: child process created\n" );
*q = 73;
printf( "PARENT: *q is %d\n", *q );
}
return EXIT_SUCCESS;
}
2
Graded problems
Complete the problems below and submit via Submitty for a grade. Please do not post any answers
to these questions. All work on these problems is to be your own.
1. Write code to display the output shown below in the exact given order (i.e., do not allow
interleaving to occur).
Write all of your code in lecex2-q1.c for this problem.
You must call both fork() and waitpid() to complete this problem. Each line of output
that starts with "PARENT" must be displayed by the parent (original) process; likewise, each
line of output that starts with "CHILD" must be displayed by the child process.
bash$ ./a.out
PARENT: start here!
CHILD: happy birthday to me!
CHILD: idk......good-bye!
PARENT: child process terminated.
PARENT: sigh, i'm gonna miss that little child process.
bash$
2. Copy your solution from above and modify it to have the parent (original) process create two
child processes. Your program must display the output shown below in the exact given order.
Again use both fork() and waitpid() to complete this problem.
Write all of your code in lecex2-q2.c for this problem.
As above, each line of output that starts with "PARENT" must be displayed by the parent
(original) process. Further, each line of output that starts with "CHILD A" must be displayed
by the first child process; and each line of output that starts with "CHILD B" must be displayed
by the second child process.
Be sure you have one parent process with two child processes, though note that both child
processes do not need to exist simultaneously. More specifically, create one child process, wait
for it to terminate, then create the second child process.
bash$ ./a.out
PARENT: start here!
CHILD A: happy birthday to me!
CHILD A: idk......good-bye!
CHILD B: and happy birthday to me!
CHILD B: nothing to do.
PARENT: both child processes terminated.
PARENT: end here!
bash$
3
3. Review the forked.c code posted along with this lecture exercise (also shown on the next
page). Do not change the forked.c code or submit this code to Submitty. Submitty will
compile your own code file in with this given forked.c code.
In the forked.c code, the parent process calls a lecex2_parent() function, whereas the
child process calls a lexec2_child() function. Your task is to write these two functions in
your own fork-functions.c code file. Each of these functions is described below.
Only submit your fork-functions.c code file for this problem.
In the lecex2_child() function, you must open and read from a file called data.txt.
Using any technique you would like, read/identify the nth character in that file, then
close the file.
If all is successful, exit the child process and return the nth character as its exit status.
If instead an error occurs, display an error message to stderr and use the abort()
library function to abnormally terminate the child process. Check the man page for
abort() for more details.
In the lecex2_parent() function, you must wait for the child process to terminate by
using waitpid().
If the child process terminated abnormally, display the following line of output and
return EXIT_FAILURE:
PARENT: child process terminated abnormally!
If instead the child process terminated normally, display the following line of output and
return EXIT_SUCCESS:
PARENT: child process returned '<char>'
Note that <char> here represents the one-byte exit status received from the child process
and should be displayed as a single character. As an example, if 'Q' was the nth character
read by the child, the parent would output:
PARENT: child process returned 'Q'
(v1.1) Note that a typo was fixed in the line of output shown above.
4
/* forked.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int n = 7; /* or some other value ... */
int rc;
if ( p == -1 )
{
perror( "fork() failed" );
return EXIT_FAILURE;
}
if ( p == 0 )
{
rc = lecex2_child( n );
}
else /* p > 0 */
{
rc = lecex2_parent();
}
return rc;
}