กระบวนการซอมบี้

บนระบบปฏิบัติการคอมพิวเตอร์ แบบ UnixและUnixกระบวนการซอมบี้หรือกระบวนการที่เลิกใช้งานเป็นกระบวนการที่เสร็จสิ้นการดำเนินการ (ผ่านการเรียกของระบบ ) แต่ยังคงมีรายการอยู่ในตารางกระบวนการ : เป็นกระบวนการใน " สถานะสิ้นสุด " สิ่งนี้เกิดขึ้นสำหรับกระบวนการลูกโดยที่รายการยังคงจำเป็นเพื่อให้กระบวนการหลักอ่านสถานะการออก ของลูก : เมื่อสถานะทางออกถูกอ่านผ่าน การเรียกของระบบรายการของซอมบี้จะถูกลบออกจากตารางกระบวนการและมีการกล่าวถึง ได้รับการ "เก็บเกี่ยว" กระบวนการลูกเริ่มแรกจะกลายเป็นซอมบี้ จากนั้นจึงถูกลบออกจากตารางทรัพยากร ภายใต้การทำงานของระบบปกติ ซอมบี้จะถูกผู้ปกครองรอทันที จากนั้นระบบจะเก็บเกี่ยวซอมบี้ กระบวนการที่คงสภาพซอมบี้ไว้เป็นเวลานานมักเป็นข้อผิดพลาดและอาจทำให้ทรัพยากรรั่วไหลได้ โดยทั่วไปแล้ว ทรัพยากรเคอร์เนลเดียวที่พวกเขาครอบครองคือรายการตารางกระบวนการ รหัสกระบวนการของพวกเขา อย่างไรก็ตาม ซอมบี้ยังสามารถเปิดบัฟเฟอร์ไว้ได้ และใช้หน่วยความจำ ซอมบี้สามารถจับตัวอธิบายไฟล์ได้ ซึ่งจะป้องกันไม่ให้พื้นที่สำหรับไฟล์เหล่านั้นอยู่ในระบบไฟล์ผลกระทบนี้สามารถเห็นได้จากความแตกต่างระหว่างและในขณะที่อาจแสดงพื้นที่ว่างในดิสก์จำนวนมาก แต่จะแสดงพาร์ติชันทั้งหมด หากซอมบี้ไม่ได้รับการทำความสะอาด สิ่งนี้อาจเติมเต็มพาร์ติชันรูทและทำให้ระบบเสียหาย exit wait dudfdudf

คำว่ากระบวนการซอมบี้มาจากคำจำกัดความทั่วไปของซอมบี้ - คนที่ไม่ตายในคำอุปมา กระบวนการเด็กได้ "ตาย" แต่ยังไม่ได้รับการ " เก็บเกี่ยว " ไม่เหมือนกับกระบวนการปกติkillคำสั่งไม่มีผลกับกระบวนการซอมบี้

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

ภาพรวม

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

หลังจากที่ซอมบี้ถูกลบออกแล้วตัวระบุกระบวนการ (PID) และรายการในตารางกระบวนการจะสามารถนำมาใช้ซ้ำได้ อย่างไรก็ตาม หากผู้ปกครองไม่สามารถโทรได้waitซอมบี้ก็จะถูกทิ้งไว้ในตารางกระบวนการ ส่งผลให้ ทรัพยากร รั่วไหลในบางสถานการณ์ สิ่งนี้อาจเป็นที่พึงปรารถนา - กระบวนการหลักประสงค์ที่จะถือทรัพยากรนี้ต่อไป - ตัวอย่างเช่น หากผู้ปกครองสร้างกระบวนการลูกอื่น ก็จะทำให้แน่ใจได้ว่ามันจะไม่ได้รับการจัดสรร PID เดียวกัน ในระบบที่คล้าย UNIX สมัยใหม่ (ซึ่งสอดคล้องกับ ข้อกำหนด SUSv3ในส่วนนี้) จะมีกรณีพิเศษต่อไปนี้: ถ้าพาเรนต์ ละเว้น SIGCHLD อย่างชัดเจนโดยการตั้งค่าตัวจัดการเป็นSIG_IGN(แทนที่จะเพิกเฉยต่อสัญญาณโดยค่าเริ่มต้น) หรือมีSA_NOCLDWAITการตั้งค่าสถานะ ข้อมูลสถานะการออกของเด็กทั้งหมดจะถูกยกเลิก และไม่มีกระบวนการซอมบี้เหลืออยู่[1]

สามารถระบุซอมบี้ได้ในเอาต์พุตจากps คำสั่ง Unix โดยมี " Z" ในคอลัมน์ "STAT" [2]ซอมบี้ที่มีอยู่นานกว่าช่วงระยะเวลาสั้นๆ มักจะบ่งบอกถึงจุดบกพร่องในโปรแกรมหลัก หรือเป็นเพียงการตัดสินใจที่ไม่ปกติที่จะไม่เก็บเกี่ยวเด็ก (ดูตัวอย่าง) หากโปรแกรมหลักไม่ทำงานอีกต่อไป กระบวนการซอมบี้มักจะระบุจุดบกพร่องในระบบปฏิบัติการ เช่นเดียวกับการรั่วไหลของทรัพยากรอื่นๆ การมีอยู่ของซอมบี้สองสามตัวนั้นไม่ได้น่ากังวลในตัวเอง แต่อาจบ่งบอกถึงปัญหาที่จะร้ายแรงขึ้นภายใต้ภาระที่หนักกว่า เนื่องจากไม่มีการจัดสรรหน่วยความจำให้กับกระบวนการซอมบี้ - การใช้หน่วยความจำระบบเพียงอย่างเดียวคือสำหรับรายการตารางกระบวนการ - ข้อกังวลหลักเกี่ยวกับซอมบี้จำนวนมากไม่ได้อยู่ที่หน่วยความจำไม่เพียงพอ แต่เป็นการสิ้นเปลืองรายการตารางกระบวนการ ตัวเลข ID ของการประมวลผลอย่างเป็นรูปธรรม อย่างไรก็ตาม ซอมบี้สามารถเก็บบัฟเฟอร์แบบเปิดที่เกี่ยวข้องกับตัวอธิบายไฟล์ได้ และทำให้ซอมบี้ใช้หน่วยความจำ ซอมบี้ยังสามารถเก็บคำอธิบายไฟล์ไว้ในไฟล์ที่ถูกลบไปแล้วได้ วิธีนี้จะป้องกันไม่ให้ระบบไฟล์กู้คืน i-nodes สำหรับไฟล์ที่ถูกลบ ดังนั้นคำสั่งเพื่อแสดงการใช้งานดิสก์จะไม่นับไฟล์ที่ถูกลบซึ่งไม่สามารถนำพื้นที่กลับมาใช้ใหม่ได้เนื่องจากมีซอมบี้ถือ filedescriptor

หากต้องการลบซอมบี้ออกจากระบบสามารถส่งสัญญาณkill SIGCHLD ไปยังพาเรนต์ด้วยตนเองได้ โดยใช้ คำสั่ง หากกระบวนการหลักยังคงปฏิเสธที่จะเก็บเกี่ยวซอมบี้ และหากสามารถยุติกระบวนการหลักได้ ขั้นตอนต่อไปก็คือการลบกระบวนการหลักออก เมื่อกระบวนการสูญเสียพาเรนต์initไป จะกลายเป็นพาเรนต์ใหม่initดำเนินwaitการเรียกของระบบเป็นระยะเพื่อเก็บเกี่ยวซอมบี้ใด ๆ ที่initเป็นพาเรนต์

ตัวอย่าง

การรอกระบวนการลูกที่เฉพาะเจาะจงตามลำดับ (เฉพาะ) แบบซิ งโครนัสอาจทำให้ซอมบี้ปรากฏนานกว่า "ช่วงเวลาสั้น ๆ" ที่กล่าวถึงข้างต้น ไม่จำเป็นต้องเป็นข้อบกพร่องของโปรแกรม

#include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> 
 
 
 

int main ( โมฆะ) { pid_t pids [ 10 ]; ฉัน; 

     
     

    สำหรับ( i = 9 ; i >= 0 ; -- i ) { pids [ i ] = fork (); ถ้า( pids [ i ] == 0 ) { printf ( "Child%d \n " , i ); นอน( i + 1 ); _ออก( 0 ); } }        
          
            
             
            
            
        
    

    สำหรับ( i = 9 ; i >= 0 ; -- i ) { printf ( "parent%d \n " , i ); waitpid ( พิด[ i ], NULL , 0 ); -        
         
          
    

    กลับ0 ; - 

เอาท์พุต

ผู้ปกครอง9
เด็ก3
เด็ก4
เด็ก2
เด็ก5
เด็ก1
เด็ก6
เด็ก0
เด็ก7
เด็ก8
Child9 // ที่นี่หยุดชั่วคราว
พ่อแม่8
ผู้ปกครอง7
ผู้ปกครอง6
ผู้ปกครอง5
ผู้ปกครอง4
ผู้ปกครอง3
ผู้ปกครอง2
ผู้ปกครอง1
ผู้ปกครอง0

คำอธิบาย

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

ในระหว่างการวนซ้ำ อาร์เรย์ของรหัสกระบวนการลูกจะถูกสร้างขึ้น มีสำเนาของอาร์เรย์ pids[] ในกระบวนการทั้งหมด 11 กระบวนการ แต่เฉพาะในพาเรนต์เท่านั้นที่เสร็จสมบูรณ์ - สำเนาในแต่ละรายการย่อยจะหายไป PID ลูกที่มีหมายเลขต่ำกว่า และจะมีศูนย์สำหรับ PID ของตัวเอง (ไม่ใช่ว่าเรื่องนี้สำคัญนัก เนื่องจากมีเพียงกระบวนการหลักเท่านั้นที่ใช้อาร์เรย์นี้จริงๆ)

วงที่สองดำเนินการเฉพาะในกระบวนการหลักเท่านั้น (เนื่องจากรายการย่อยทั้งหมดได้ออกก่อนถึงจุดนี้) และรอให้รายการย่อยแต่ละรายการออก โดยจะรอเด็กที่เข้านอน 10 วินาทีก่อน ข้อความอื่นๆ ทั้งหมดออกจากระบบไปนานแล้ว ดังนั้นข้อความทั้งหมด (ยกเว้นข้อความแรก) จึงปรากฏต่อเนื่องกันอย่างรวดเร็ว ไม่มีความเป็นไปได้ของการสั่งซื้อแบบสุ่มที่นี่ เนื่องจากมันถูกขับเคลื่อนโดยการวนซ้ำในกระบวนการเดียว ข้อความพาเรนต์แรกปรากฏขึ้นจริงก่อนข้อความลูกใดๆ - พาเรนต์สามารถดำเนินการต่อในวงที่สองก่อนที่กระบวนการลูกใดๆ จะสามารถเริ่มต้นได้ นี่เป็นเพียงพฤติกรรมแบบสุ่มของตัวกำหนดเวลากระบวนการอีกครั้ง - ข้อความ "parent9" อาจปรากฏขึ้นที่ใดก็ได้ในลำดับก่อนหน้า "parent8"

Child0 ถึง Child8 ใช้เวลาอย่างน้อยหนึ่งวินาทีในสถานะนี้ ระหว่างเวลาที่ออกและเวลาที่ผู้ปกครองทำการ waitpid() กับพวกเขา ผู้ปกครองกำลังรอ Child9 อยู่แล้วก่อนที่มันจะออก ดังนั้นกระบวนการหนึ่งจึงไม่ใช้เวลาเหมือนซอมบี้เลย[3]

ดูสิ่งนี้ด้วย

อ้างอิง

  1. ^ "รอ (2) หน้าคน" คู่มือโปรแกรมเมอร์ Linux
  2. ^ "ซอมบี้ (5) - ระบบ UNIX V (แนวคิด)" เครื่องตรวจจับการชนกันที่ Fermilab
  3. "Linux - ใครช่วยอธิบายวิธีการทำงานหน่อยได้ไหม?fork(),sleep()"
  • "หน้าคู่มือ UNIX : ps ()" UNIXhelp สำหรับผู้ใช้ เก็บถาวรจากต้นฉบับเมื่อ 2013-03-08.

ลิงค์ภายนอก

  • โพสต์ usenet กระบวนการซอมบี้
  • คำถามที่พบบ่อยเกี่ยวกับ UNIX 3.13: ฉันจะกำจัดกระบวนการซอมบี้ที่ต่อเนื่องได้อย่างไร?
ดึงมาจาก "https://en.wikipedia.org/w/index.php?title=Zombie_process&oldid=1199056670"