โปรแกรมจะทำอย่างไรเมื่อมีการส่งสัญญาณ SIGKILL


39

เมื่อฉันเคยkillall -9 nameฆ่าโปรแกรมสถานะกลายเป็นซอมบี้ ไม่กี่นาทีต่อมามันหยุดลงจริงๆ ดังนั้นจะเกิดอะไรขึ้นในช่วงเวลาเหล่านั้น

คำตอบ:


66

โปรแกรมไม่เคยได้รับสัญญาณ SIGKILL เนื่องจาก SIGKILL ได้รับการจัดการโดยระบบปฏิบัติการ / เคอร์เนลอย่างสมบูรณ์

เมื่อ SIGKILL สำหรับกระบวนการเฉพาะถูกส่งตัวจัดตารางเวลาของเคอร์เนลจะหยุดให้เวลาประมวลผลนั้นอีกต่อไปสำหรับการรันรหัสพื้นที่ผู้ใช้ หากกระบวนการมีเธรดใด ๆ ที่เรียกใช้งานรหัสพื้นที่ผู้ใช้บน CPUs / cores อื่น ๆ ณ เวลาที่ตัวกำหนดตารางเวลาทำการตัดสินใจนี้เธรดเหล่านั้นจะหยุดทำงานเช่นกัน (ในระบบแบบ single-core สิ่งนี้เคยง่ายกว่านี้มาก: ถ้ามี CPU core เพียงตัวเดียวในระบบที่กำลังรันตัวกำหนดตารางเวลาโดยนิยามไม่ได้ใช้กระบวนการในเวลาเดียวกัน!)

หากกระบวนการ / เธรดกำลังเรียกใช้งานรหัสเคอร์เนล (เช่นการเรียกใช้ระบบหรือการดำเนินการ I / O ที่เชื่อมโยงกับไฟล์หน่วยความจำที่แมป) ในขณะที่ SIGKILL นั้นจะได้รับบิตที่ยากขึ้น: การเรียกระบบบางอย่างจะขัดจังหวะ เคอร์เนลทำเครื่องหมายภายในกระบวนการว่าอยู่ในสถานะ "ตาย" พิเศษจนกว่าการเรียกของระบบหรือการดำเนินการ I / O จะได้รับการแก้ไข เวลาซีพียูในการแก้ไขปัญหาเหล่านั้นจะถูกกำหนดไว้ตามปกติ การเรียกใช้ระบบขัดจังหวะหรือการดำเนินการ I / O จะตรวจสอบว่ากระบวนการที่เรียกพวกเขากำลังจะตายที่จุดหยุดที่เหมาะสมและจะออกจากต้นในกรณีนั้นหรือไม่ การทำงานของ Uninterruptible จะทำงานจนเสร็จและจะตรวจสอบสถานะ "กำลังจะตาย" ก่อนที่จะกลับไปที่รหัสพื้นที่ผู้ใช้

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

ดังนั้นกระบวนการเองจะไม่ได้รับโอกาสในการประมวลผลข้อมูลที่ได้รับ SIGKILL

เมื่อโปรเซสอยู่ในสถานะ "zombie" หมายความว่าโปรเซสนั้นตายแล้ว แต่โปรเซสหลักนั้นยังไม่ได้รับการยอมรับโดยการอ่านรหัสทางออกของกระบวนการที่ตายแล้วโดยใช้การwait(2)เรียกระบบ โดยพื้นฐานแล้วทรัพยากรเพียงอย่างเดียวที่กระบวนการซอมบี้ใช้ไปมากคือสล็อตในตารางกระบวนการที่เก็บ PID ของตนรหัสทางออกและ "สถิติสำคัญ" อื่น ๆ ของกระบวนการในช่วงเวลาที่เสียชีวิต

หากกระบวนการผู้ปกครองเสียชีวิตก่อนที่จะมีเด็กกระบวนการเด็กกำพร้าถูกนำมาใช้โดยอัตโนมัติโดย PID # 1 ซึ่งมีหน้าที่พิเศษที่จะเรียกต่อไปเพื่อให้wait(2)กระบวนการเด็กกำพร้าใด ๆ จะไม่ติดอยู่ในฐานะซอมบี้

หากกระบวนการซอมบี้ใช้เวลาหลายนาทีในการล้างมันแสดงให้เห็นว่ากระบวนการหลักของซอมบี้กำลังดิ้นรนหรือไม่ทำงานอย่างถูกต้อง

มีคำอธิบายแบบลิ้น - แก้มเกี่ยวกับสิ่งที่ต้องทำในกรณีที่มีปัญหาเกี่ยวกับซอมบี้ในระบบปฏิบัติการยูนิกซ์ - เหมือน: "คุณไม่สามารถทำอะไรให้กับพวกซอมบี้ตัวเองราวกับว่าพวกเขาตายแล้วแทนที่จะฆ่านายซอมบี้ชั่วร้าย! " (เช่นกระบวนการหลักของซอมบี้ที่ลำบาก)


5
จะเกิดอะไรขึ้นถ้ากระบวนการอยู่ในการเรียกใช้เคอร์เนล (เช่นทำ I / O) เมื่อส่ง SIGKILL?
gidds

9
@gidds ทั้ง I / O จะถูกยกเลิกเพื่อใช้งาน SIGKILL หรือ SIGKILL จะล่าช้าจนกว่า I / O จะเสร็จสิ้น นี่คือความแตกต่างระหว่าง 'S' และ 'D' สถานะสลีปในps: 'S' สำหรับ I / O รอให้เคอร์เนลสามารถยกเลิกเพื่อส่งสัญญาณและ 'D' สำหรับสิ่งที่ไม่สามารถทำได้
zwol

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

4
@gidds มีสถานะที่แตกต่างกันอย่างน้อยสี่สถานะที่สามารถดำเนินการได้สามารถเรียกใช้รหัสเคอร์เนลได้ในขณะนี้หรือสามารถนอนในหนึ่งในสามสถานะการนอนหลับที่แตกต่างกัน สถานะสลีปสามารถขัดจังหวะไม่ขัดจังหวะหรือไม่ขัดจังหวะยกเว้นสัญญาณร้ายแรง ถ้ามันอยู่ในการนอนแบบไม่ขัดจังหวะมันจะถูกปล่อยให้นอนหลับตราบเท่าที่มันต้องการและเพียงแค่เมื่อมันตื่นขึ้นก็จะมีโอกาสที่จะตาย หากอยู่ในสถานะสลีปอื่น ๆ อีกสองสถานะจะถูกปลุกขึ้นมาทันทีและกำหนดเวลาทันทีที่มี CPU สำหรับมัน
kasperd

2
@gidds จะเกิดอะไรขึ้นต่อไปขึ้นอยู่กับรหัสเคอร์เนลที่ใช้ ไม่ว่าจะใช้งานมาก่อนหรือไม่ก็ต้องตื่นขึ้นมาก่อนและจากนั้นสามารถเริ่มรันโค้ดเคอร์เนลที่อยู่ในเวลานั้นจะได้รับอนุญาตให้ดำเนินการต่อ และรหัสเคอร์เนลนั้นมีหน้าที่รับผิดชอบในการสังเกตว่ากระบวนการนั้นได้รับการบอกให้ตาย ส่วนใหญ่วิธีที่เหมาะสมในการจัดการกับสิ่งนั้นในเคอร์เนลรหัสคือเพียงแค่ส่งคืนข้อผิดพลาดจากฟังก์ชันใด ๆ ก็ตามที่มันถูกเรียกใช้งาน เมื่อสแตกการเรียกเคอร์เนลได้รับการคลายรหัสการจัดการสัญญาณสามารถใช้เวลาก่อนที่จะกลับไปที่โหมดผู้ใช้
kasperd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.