ptg10805159
246 Process Control Chapter 8
We saw a potential race condition in the program in Figure8.8 when the second
child printed its parent process ID. If the second child runs beforethe first child, then
its parent process will be the first child. But if the first child runs first and has enough
time toexit,then the parent process of the second child isinit.Even callingsleep,
as we did, guarantees nothing. If the system was heavily loaded, the second child could
resume aftersleepreturns, beforethe first child has a chance to run. Problems of this
form can be difficult to debug because they tend to work ‘‘most of the time.’’
Aprocess that wants to wait for a child to terminate must call one of thewait
functions. Ifaprocess wants to wait for its parent to terminate, as in the program from
Figure8.8, a loop of the following form could be used:
while (getppid() != 1)
sleep(1);
The problem with this type of loop, calledpolling, is that it wastes CPU time, as the
caller is awakened every second to test the condition.
To avoid race conditions and to avoid polling, some form of signaling is required
between multiple processes. Signals can be used for this purpose, and we describe one
way to do this in Section 10.16.Various forms of interprocess communication(IPC)can
also be used.We’ll discuss some of these options in Chapters 15 and 17.
For a parent and child relationship, we often have the following scenario. After the
fork,both the parent and the child have something to do. For example, the parent
could update a record in a log file with the child’s process ID, and the child might have
to create a file for the parent. In this example, we requirethat each process tell the other
when it has finished its initial set of operations, and that each wait for the other to
complete, beforeheading off on its own. The following code illustrates this scenario:
#include "apue.h"
TELL_WAIT(); /* set things up for TELL_xxx & WAIT_xxx */
if ((pid = fork()) < 0) {
err_sys("fork error");
}else if (pid == 0) { /* child */
/* child does whatever is necessary ... */
TELL_PARENT(getppid()); /* tell parent we’re done */
WAIT_PARENT(); /* and wait for parent */
/* and the child continues on its way ... */
exit(0);
}
/* parent does whatever is necessary ... */
TELL_CHILD(pid); /* tell child we’re done */
WAIT_CHILD(); /* and wait for child */
/* and the parent continues on its way ... */
exit(0);