Ответ 1
В вашем коде зомби создается на exit(0)
(комментарий со стрелкой ниже):
pid=fork();
if (pid==0) {
exit(0); // <--- zombie is created on here
} else {
// some parent code ...
}
Почему? Потому что на нем никогда не было wait
. Когда что-то вызывает waitpid(pid)
, он возвращает посмертную информацию о процессе, например, код выхода. К сожалению, когда процесс завершен, ядро не может просто избавиться от этой записи процесса, иначе код возврата будет потерян. Таким образом, он ждет кого-то на wait
на нем и оставляет эту запись процесса даже в том случае, если она действительно не занимает никакой памяти, кроме записи в таблице процессов - это именно то, что называется зомби.
У вас мало возможностей избежать создания зомби:
-
Добавить
waitpid()
в родительский процесс. Например, это поможет:pid=fork(); if (pid==0) { exit(0); } else { waitpid(pid); // <--- this call reaps zombie // some parent code ... }
-
Выполните двойную
fork()
, чтобы получить внука и выйти из ребенка, пока внук все еще жив. Внуки будут автоматически принятыinit
, если их родитель (наш ребенок) умрет, а это означает, что если внук умрет, он будет автоматическиwait
ed наinit
. Другими словами, вам нужно сделать что-то вроде этого:pid=fork(); if (pid==0) { // child if (fork()==0) { // grandchild sleep(1); // sleep a bit to let child die first exit(0); // grandchild exits, no zombie (adopted by init) } exit(0); // child dies first } else { waitpid(pid); // still need to wait on child to avoid it zombified // some parent code ... }
-
Явно игнорировать сигнал SIGCHLD в родительском. Когда ребенок умирает, родитель получает сигнал
SIGCHLD
, который позволяет ему реагировать на смерть детей. Вы можете вызватьwaitpid()
после получения этого сигнала, или вы можете установить явный обработчик сигнала игнорирования (используяsignal()
илиsigaction()
), который будет гарантировать, что ребенок не станет зомби. Другими словами, что-то вроде этого:signal(SIGCHLD, SIG_IGN); // <-- ignore child fate, don't let it become zombie pid=fork(); if (pid==0) { exit(0); // <--- zombie should NOT be created here } else { // some parent code ... }