CIS 307: Guidelines for the solution of Homework 3

Organization of the code

We have four processes - PARENT, CHILD1, CHILD2 and CHILD3. CHILD1 and CHILD2 execute in the same address space as PARENT while CHILD3 switches to a new program image during the course of its evolution. Thus we may organize the code for PARENT, CHILD1, CHILD2 and a part of the code for CHILD3 in a file, say parent.c, and put the new program for CHILD3 in a separate file, say child3.c. Since CHILD1 and CHILD2 perform the same sequence of operations, they may be implemented by calls to the same function (with different values for the arguments representing the names of files etc.) following the return from fork().

CHILD3 executes code from parent.c upon return from fork(). After displaying its own and its parent's Process ID's it invokes one of the exec family of functions, say execvp, to switch to the new program in child3.c. It should be remembered that child3.c contains a full-fledged program, and has the function main() defined in it. As explained in the statement of the problem, this program writes on the screen the Process ID and the Real User ID of the calling process, and the Process ID of its parent. All the exec functions require the name of the executable file for the new program as the first argument and so we invoke the function of our choice with the character string constant "child3" as the first argument. Since the call to this exec function is made from parent.c, it behooves us to compile child3.c and have the object code placed in the file child3 (through the command cc child3.c -o child3) before we compile parent.c.

Suggested format for the screen output

Once the processes CHILD1, CHILD2, and CHILD3 are created by PARENT, all four processes execute concurrently and write information on the screen. Thus screen outputs from the processes are likely to be interleaved or otherwise mixed up, and may not be intelligible if care is not taken to structure the output statements properly. Numeric values representing ID's are easier to format using printf, and so it would be a good idea to use printfs for the screen writes. However printf buffers output and writes to the screen only when a newline is encountered. If each independent piece of output from a process can be made to fit on a line (80 characters long) and terminated with a newline, we can prevent outputs from multiple processes from interfering with one another. In addition, each piece of output from a process should include the identity of the process to enable us to identify the writer. The following are examples of the general format :

PARENT : My PID is .......
PARENT : My parent's PID is .....
PARENT : The parameters of the program call are .. .. .. .. .. ..
......
CHILD2 : My PID is .......
CHILD3 : My PID is .......
CHILD2 : My parent's PID is .....
....
PARENT : CHILD1 (PID ....) terminated at time ......
CHILD3 : My PID (from new program) is .....
CHILD1 : My PID is ....
.....

Choice of functions for file I/O

File operations may be accomplished through Unix primitives or ANSI C library functions. The former allow greater control over certain I/O operations that may be used to advantage in our solution. The contents of the files fn3 and fn5 depend in general on the speeds of CHILD1 and CHILD2 relative to each other. An interesting phenomenon can be observed if the writes of CHILD1 and CHILD2 into fn3 and fn5 respectively can be made to interleave with one another. Specifying the O_SYNC option (to make the writes wait until physical I/O is done) while opening fn3 and fn5 using the open function, and reading from fn1 relatively small chunks (eg., 4 bytes) in each invocation of the read function would help us bring about sequences of interleaved writes.
amandala@astro.ocis.temple.edu