Volgograd

Волгоград Linux User Group

Организована 23 ноября 2002 года

Проект заморожен Птн Июл 6 02:11:14 MSD 2012


Вход:  Пароль:  

AvramenkoAndrew/defunct


Процессы Зомби


Статью постараюсь перевести, просто столкнулся сам, необходима была срочна информация, поэтому скопировал в удобное место. Русской документации не верьте, врут люди. Сами не знают и других с толку сбивают.

Обычно избавится от таких процессов можно убив родительский.

What is a zombie?


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).

How do I prevent them from occuring?


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.