เช่นเดียวกับซอมบี้ที่เกิดขึ้นจริงกระบวนการซอมบี้ไม่สามารถฆ่าได้เพราะมันตายไปแล้ว
มันเกิดขึ้นได้อย่างไร
เมื่ออยู่ใน Linux / Unix กระบวนการจะหยุด / สิ้นสุดข้อมูลทั้งหมดจากกระบวนการจะถูกลบออกจากหน่วยความจำระบบเฉพาะตัวอธิบายกระบวนการเท่านั้น กระบวนการเข้าสู่สถานะ Z (ซอมบี้) กระบวนการหลักของเขาได้รับสัญญาณจากเคอร์เนล: SIGCHLD
ซึ่งหมายความว่าหนึ่งในกระบวนการลูกของเขาออกจากถูกขัดจังหวะหรือดำเนินการต่อหลังจากถูกขัดจังหวะ (ในกรณีของเรามันออกจากเพียง)
ตอนนี้กระบวนการพาเรนต์จะต้องเรียกใช้wait()
syscall เพื่ออ่านสถานะการออกและข้อมูลอื่น ๆ จากกระบวนการลูกของเขา จากนั้น descriptor จะถูกลบออกจากหน่วยความจำและกระบวนการไม่ได้เป็นซอมบี้อีกต่อไป
หากกระบวนการหลักไม่เคยเรียกwait()
syscall ตัวอธิบายกระบวนการซอมบี้จะยังคงอยู่ในหน่วยความจำและกินสมอง โดยปกติคุณจะไม่เห็นกระบวนการซอมบี้เนื่องจากขั้นตอนด้านบนใช้เวลาน้อยลง
รุ่งอรุณแห่งความตาย
ตัวอธิบายกระบวนการแต่ละอันต้องการหน่วยความจำเพียงเล็กน้อยดังนั้นซอมบี้บางตัวจึงไม่อันตรายมาก (เหมือนในชีวิตจริง) ปัญหาหนึ่งคือกระบวนการซอมบี้แต่ละอันจะเก็บ id กระบวนการของเขาไว้และระบบปฏิบัติการ Linux / Unix มีจำนวน pid ที่ จำกัด หากซอฟต์แวร์ที่ตั้งโปรแกรมไม่ถูกต้องสร้างกระบวนการซอมบี้จำนวนมากมันอาจเกิดขึ้นได้ว่ากระบวนการไม่สามารถเริ่มต้นได้อีกต่อไปเพราะไม่มีรหัสกระบวนการมากขึ้น
ดังนั้นหากพวกเขาอยู่ในกลุ่มใหญ่พวกเขาจะอันตรายมาก (เหมือนในภาพยนตร์หลายเรื่องที่แสดงให้เห็นเป็นอย่างดี)
เราจะป้องกันตัวเองจากฝูงซอมบี้ได้อย่างไร?
การยิงที่หัวจะใช้งานได้ แต่ฉันไม่รู้คำสั่งสำหรับสิ่งนั้น (SIGKILL จะไม่ทำงานเพราะกระบวนการตายไปแล้ว)
ทีนี้คุณสามารถส่ง SIGCHLD ผ่าน kill ไปยังโพรเซสแม่ แต่เมื่อมันละเว้นสัญญาณนี้แล้วจะเป็นอย่างไร? ตัวเลือกเดียวของคุณคือฆ่ากระบวนการผู้ปกครองและกระบวนการเริ่มต้น "adopts" ซอมบี้ ตอนแรกเรียกwait()
syscall เป็นระยะเพื่อล้างลูกซอมบี้ของเขา
ในกรณีของคุณ
ในกรณีของคุณคุณต้องส่ง SIGCHLD ไปยังกระบวนการ crond:
root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit
จากนั้นอีกเทอร์มินัล:
root@host:~$ kill -17 $(pgrep cron)
ผลลัพธ์คือ:
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
คุณเห็นwait4()
syscall คืนค่า -1 ECHILD ซึ่งหมายความว่าไม่มีกระบวนการลูก ดังนั้นข้อสรุปคือ: cron ตอบสนองต่อ SIGCHLD syscall และไม่ควรบังคับให้เปิดเผย