Gerçek zombi gibi, bir zombi süreci öldürülemez, çünkü zaten ölüdür.
Nasıl olur
Linux / Unix'te bir işlem öldüğünde / bittiğinde, işlemden tüm bilgiler sistem belleğinden kaldırılır, yalnızca işlem tanımlayıcısı kalır. İşlem Z durumuna (zombi) girer. Ana süreci çekirdekten bir sinyal alır: SIGCHLD
yani, çocuk süreçlerinden biri kesilir, kesildikten sonra kesilir veya devam eder (bizim durumumuzda sadece çıkar).
Ana işlemin artık wait()
çıkış durumunu ve alt işlemindeki diğer bilgileri okumak için sistem çağrısını yürütmesi gerekir . Sonra tanımlayıcı bellekten kaldırılır ve işlem artık bir zombi değildir.
Üst işlem hiçbir zaman wait()
sistem çağrısını çağırmazsa, zombi işlem tanımlayıcısı bellekte kalır ve beyin yer. Normalde zombi süreçlerini görmezsiniz, çünkü yukarıdaki prosedür daha az zaman alır.
Ölülerin Şafağı
Her işlem tanımlayıcısının çok az miktarda belleğe ihtiyacı vardır, bu nedenle birkaç zombi çok tehlikeli değildir (gerçek hayatta olduğu gibi). Bir sorun, her zombi işleminin işlem kimliğini tutması ve bir Linux / Unix işletim sisteminin sınırlı sayıda pid'e sahip olmasıdır. Hatalı programlanmış bir yazılım çok sayıda zombi işlemi üretirse, artık işlem kimliği kullanılamadığından işlemlerin başlatılamayacağı ortaya çıkabilir.
Yani, büyük gruplardalarsa çok tehlikelidirler (birçok filmde olduğu gibi çok iyi gösterilmektedir)
Kendimizi zombi sürüsüne karşı nasıl savunabiliriz?
Kafadaki bir atış işe yarayacaktır, ama bunun için komutu bilmiyorum (SIGKILL işe yaramaz çünkü süreç zaten öldü).
Peki, SIGCHLD'u öldürme yoluyla ana işleme gönderebilirsiniz, ancak bu sinyali yoksayarsa ne olacak? Tek seçeneğiniz ana süreci öldürmek ve init sürecinin zombi "benimsemesidir". Init, düzenli olarak wait()
zombi çocuklarını temizlemek için sistem çağrısını çağırır .
Senin durumunda
Sizin durumunuzda, SIGCHLD'u crond sürecine göndermelisiniz:
root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit
Sonra başka bir terminalden:
root@host:~$ kill -17 $(pgrep cron)
Çıktı:
restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fff51be39dc, WNOHANG, NULL) = -1 ECHILD (No child processes) <-- Here it happens
rt_sigreturn(0xffffffffffffffff) = -1 EINTR (Interrupted system call)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=1892, ...}) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x403170, [CHLD], SA_RESTORER|SA_RESTART, 0x7fd6a7e9d4a0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({42, 0}, ^C <unfinished ...>
Process 1180 detached
Görüyorsunuz wait4()
hiçbir çocuğun süreç olduğunu vasıta syscall döner -1 ECHILD. Dolayısıyla sonuç şudur: cron SIGCHLD sistem çağrısına tepki verir ve kıyameti zorlamamalıdır.