ฉันจะฆ่ากระบวนการ <defunct> ที่ parent เป็นผู้เริ่มต้นได้อย่างไร


27

การส่งกำลังแขวนอยู่บน NAS ของฉันเป็นระยะ ถ้าฉันส่ง SIGTERM มันจะไม่หายไปจากรายการกระบวนการและ<defunct>ฉลากจะปรากฏขึ้นถัดจากมัน ถ้าผมส่ง SIGKILL initก็ยังคงไม่ได้หายไปและผมก็ไม่สามารถยุติแม่เพราะแม่เป็น วิธีเดียวที่ฉันสามารถกำจัดกระบวนการและรีสตาร์ทเกียร์คือการรีบูต

ฉันตระหนักถึงสิ่งที่ดีที่สุดที่ฉันสามารถทำได้คือลองและแก้ไขการส่งข้อมูล (และฉันพยายามแล้ว) แต่ฉันเป็นผู้เริ่มต้นในการรวบรวมและฉันต้องการให้แน่ใจว่า torrents ของฉันเสร็จสิ้นก่อนที่ฉันจะเริ่มยุ่งกับมัน


3
ไม่มีใครบอกได้ชัดเจน ... กระบวนการ <defunct> ที่เป็นเจ้าของโดย "init" ไม่น่าจะเป็นไปได้! นี่เป็นคำบรรยายที่แปลกมาก! คุณแน่ใจไหม?
JoelFan

@ JoelFan: ฉันแค่มองหามันเพื่อให้แน่ใจว่าฉันไม่ได้ลืมสิ่งที่สำคัญ ซอมบี้ที่เป็นลูกinitควรจะหายไปอย่างรวดเร็วตั้งแต่initรอเด็ก ๆ เป็นระยะ ๆ เพราะเป็นหนึ่งในภารกิจทั่วไปของมัน ... <defunct>เหมือนกับซอมบี้รึเปล่า?
D.Shawley

1
ไม่เป็นไร ... <defunct>เป็นเหมือนกับซอมบี้อย่างแม่นยำ initจะรอลูกของมันดังนั้นสิ่งนี้ไม่ควรเกิดขึ้นในทางทฤษฎี ผมสงสัยว่าเกิดอะไรขึ้นถ้าคุณส่งSIGCHLDไปinit?
D.Shawley

@JoelFan: ใช่ฉันแน่ใจ ค่าสำหรับ PPID คือ 1 (init) ดังนั้นจึงเป็นไปไม่ได้ที่ SIGKILL จะดำเนินการ
Andy E

3
คล้ายกับunix.stackexchange.com/a/5648
tshepang

คำตอบ:


35

คุณไม่สามารถฆ่า<defunct>กระบวนการ (หรือเรียกอีกอย่างว่ากระบวนการซอมบี้) เนื่องจากกระบวนการนั้นตายไปแล้ว ระบบเก็บกระบวนการซอมบี้เพื่อให้ผู้ปกครองรวบรวมสถานะการออก หากผู้ปกครองไม่ได้รวบรวมสถานะทางออกจากนั้นกระบวนการซอมบี้จะอยู่ตลอดไป วิธีเดียวที่จะกำจัดกระบวนการซอมบี้เหล่านี้คือการฆ่าผู้ปกครอง หากพาเรนต์เป็นแบบเริ่มต้นคุณสามารถรีบูตได้เท่านั้น

กระบวนการซอมบี้ใช้เวลาเกือบไม่มีทรัพยากรดังนั้นจึงไม่มีค่าใช้จ่ายในการดำเนินการ แม้ว่าการมีกระบวนการซอมบี้โดยทั่วไปหมายถึงว่ามีข้อผิดพลาดในบางโปรแกรมของคุณ เริ่มแรกควรรวบรวมเด็กทุกคน หาก init มีลูกซอมบี้แล้วก็จะมีข้อผิดพลาดใน init (หรือที่อื่น แต่มีข้อผิดพลาดอยู่)

http://en.wikipedia.org/wiki/Zombie_process


9
initไม่มีลูกซอมบี้ จากบทความ wikipedia: เมื่อกระบวนการสูญเสียพาเรนต์ init จะกลายเป็นพาเรนต์ใหม่ ตอนแรกจะทำการเรียกระบบรอเพื่อเก็บเกี่ยวซอมบี้ใด ๆ ที่มี init เป็นผู้ปกครอง หนึ่งในinitหน้าที่ของเราคือการเลี้ยงเด็กกำพร้าและซอมบี้ผู้ปกครอง
D.Shawley

14
@ D.Shawley: initอาจมีข้อบกพร่อง การแทนที่ init runitมีข้อผิดพลาดที่ทำให้เกิดปัญหานี้
camh

2
init สามารถมีลูกที่ตายแล้วอาจเกิดจากข้อผิดพลาด แต่ทำได้ เพราะตอนนี้ฉันกำลังดูอยู่
studgeek

มีโปรแกรมนี้ที่ฉันวิ่งจาก terminal และเข้าสู่สถานะที่หมดอายุ .. ตามที่อธิบายโดย @lesmana เมื่อฉันปิดเทอร์มินัล (พาเรนต์) โปรแกรมออกจากโปรแกรมอย่างหมดจด
mk ..

6

ทุกคนที่พยายามแก้ไขซอร์สโค้ดการส่งข้อมูลของ C ควรอ่านคำแนะนำ "double fork" เพื่อหลีกเลี่ยงซอมบี้และตัวจัดการสัญญาณ ... และวิธีการที่สามารถใช้เป็นส่วนหนึ่งของฟังก์ชั่นการวางไข่อัจฉริยะ variadic (ดูการวางไข่ใน Unix )

excerpt from: 
   "Spawning in Unix", http://lubutu.com/code/spawning-in-unix

Double fork
This trick lets you spawn processes whilst avoiding zombies, without 
installing any signal handler. The first process forks and waits for its 
child; the second process forks and immediately exits and is reaped;
the third process is adopted by init, and executes the desired program. 
All zombies accounted for, since init is always waiting.

if(fork() == 0) {
   if(fork() == 0) {
       execvp(file, argv);
       exit(EXIT_FAILURE);
   }
   exit(EXIT_SUCCESS);
}
wait(NULL);

1
Double fork ป้องกันการประมวลผลของซอมบี้โดยบังคับให้เคอร์เนลตั้งค่าพาเรนต์เป็น PID 1 ซึ่งควรล้างค่าซอมบี้ ดูเหมือนว่าการส่งข้อมูลทำได้แล้วเนื่องจากผู้ปกครองดำเนินการอยู่แล้ว 1
Jander

1
มีหลายปัญหาที่นี่ # 1: เฉพาะผู้ปกครองเท่านั้นที่ควรเรียกexit(3); เด็กควรโทร_exit(2)แทน (มิฉะนั้นคุณจะได้รับหลาย stdio วูบวาบท่ามกลางปัญหาอื่น ๆ ) # 2: ที่execvp(3)สามารถใช้perror(3)ถ้ามันล้มเหลว # 3: คุณควรใช้signal(SIGCHLD, SIG_IGN)แทนที่จะเป็นระเบียบทั้งหมด
เควิน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.