| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When a program forks and the child finishes before the parent, the
kernel still keeps some of its information about the child in case the
parent might need it – for example, the parent may need to check the
child's exit status. To be able to get this information, the parent
calls wait(); when this happens, the kernel can discard the
information.
In the interval between the child terminating and the parent calling
wait(), the child is said to be a `zombie'. (If you do `ps', the
child will have a `Z' in its status field to indicate this.) Even
though it's not running, it's still taking up an entry in the process
table. (It consumes no other resources, but some utilities may show
bogus figures for e.g. CPU usage; this is because some parts of the
process table entry have been overlaid by accounting info to save
space.)
This is not good, as the process table has a fixed number of entries and
it is possible for the system to run out of them. Even if the system
doesn't run out, there is a limit on the number of processes each user
can run, which is usually smaller than the system's limit. This is one
of the reasons why you should always check if fork() failed, by
the way!
If the parent terminates without calling wait(), the child is `adopted'
by init, which handles the work necessary to cleanup after the
child. (This is a special system program with process ID 1 – it's
actually the first program to run after the system boots up).
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You need to ensure that your parent process calls wait() (or
waitpid(), wait3(), etc.) for every child process that
terminates; or, on some systems, you can instruct the system that you
are uninterested in child exit states.
Another approach is to fork() twice, and have the
immediate child process exit straight away. This causes the grandchild
process to be orphaned, so the init process is responsible for cleaning
it up. For code to do this, see the function fork2() in the
examples section.
To ignore child exit states, you need to do the following (check your system's manpages to see if this works):
struct sigaction sa;
sa.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
sa.sa_flags = SA_NOCLDWAIT;
#else
sa.sa_flags = 0;
#endif
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
|
If this is successful, then the wait() functions are prevented
from working; if any of them are called, they will wait until all
child processes have terminated, then return failure with
errno == ECHILD.
The other technique is to catch the SIGCHLD signal, and have the signal
handler call waitpid() or wait3(). See the examples
section for a complete program.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated on September, 10 2007 using texi2html 1.77.