วิธีฆ่ากระบวนการซอมบี้บน Linux

เผยแพร่แล้ว: 2022-01-29
หน้าต่างเทอร์มินัลบนแล็ปท็อป Linux
Fatmawati Achmad Zaenuri/Shutterstock

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

สถานะกระบวนการทำงานอย่างไรบน Linux

แน่นอน Linux ต้องติดตามแอปพลิเคชันและภูตทั้งหมดที่ทำงานบนคอมพิวเตอร์ของคุณ วิธีหนึ่งที่จะทำเช่นนี้คือการรักษาตารางกระบวนการ นี่คือรายการโครงสร้างในหน่วยความจำเคอร์เนล แต่ละกระบวนการมีรายการในรายการนี้ซึ่งมีข้อมูลบางอย่างเกี่ยวกับกระบวนการนี้

โครงสร้างตารางกระบวนการแต่ละอันมีไม่มาก พวกเขาเก็บ ID กระบวนการ รายการข้อมูลอื่นๆ สองสามรายการ และตัวชี้ไปยังบล็อกควบคุมกระบวนการ (PCB) สำหรับกระบวนการนั้น

เป็น PCB ที่มีรายละเอียดมากมายที่ Linux จำเป็นต้องค้นหาหรือตั้งค่าสำหรับแต่ละกระบวนการ PCB ยังได้รับการปรับปรุงเมื่อมีการสร้างกระบวนการ ให้เวลาในการประมวลผล และในที่สุดก็ถูกทำลาย

Linux PCB มีมากกว่า 95 ฟิลด์ มันถูกกำหนดให้เป็นโครงสร้างที่เรียกว่า task_struct.h และมีความยาวมากกว่า 700 บรรทัด PCB ประกอบด้วยข้อมูลประเภทต่อไปนี้:

  • สถานะกระบวนการ : สถานะต่างๆ ได้อธิบายไว้ด้านล่าง
  • หมายเลขกระบวนการ : ตัวระบุเฉพาะภายในระบบปฏิบัติการ
  • ตัว นับโปรแกรม : เมื่อกระบวนการนี้ได้รับการเข้าถึง CPU ในครั้งถัดไป ระบบจะใช้ที่อยู่นี้เพื่อค้นหาคำสั่งถัดไปของกระบวนการที่ควรดำเนินการ
  • Registers : รายการการลงทะเบียน CPU ที่ใช้โดยกระบวนการนี้ รายการอาจมีตัวสะสม การลงทะเบียนดัชนี และพอยน์เตอร์สแต็ก
  • เปิดรายการ ไฟล์ : ไฟล์ที่เกี่ยวข้องกับกระบวนการนี้
  • ข้อมูลการจัดกำหนดการ CPU : ใช้เพื่อกำหนดความถี่และระยะเวลาในการประมวลผลของ CPU ที่มอบให้กับกระบวนการนี้ ต้องบันทึกลำดับความสำคัญของกระบวนการ ตัวชี้ไปยังคิวการจัดกำหนดการ และพารามิเตอร์การจัดกำหนดการอื่นๆ ใน PCB
  • ข้อมูลการจัดการหน่วยความจำ : รายละเอียดเกี่ยวกับหน่วยความจำที่กระบวนการนี้ใช้ เช่น ที่อยู่เริ่มต้นและสิ้นสุดของหน่วยความจำกระบวนการ และตัวชี้ไปยังหน้าหน่วยความจำ
  • ข้อมูลสถานะ I/O : อุปกรณ์ขาเข้าหรือขาออกที่ใช้โดยกระบวนการ

“สถานะกระบวนการ” สามารถเป็นอย่างใดอย่างหนึ่งต่อไปนี้:

  • R: กระบวนการทำงานหรือรันได้ ทำงานหมายความว่าได้รับรอบ CPU และดำเนินการ กระบวนการที่รันได้พร้อมที่จะรันและรอสล็อต CPU
  • S: กระบวนการนอนหลับ. กระบวนการกำลังรอการดำเนินการให้เสร็จสิ้น เช่น การดำเนินการขาเข้าหรือขาออก หรือทรัพยากรที่จะพร้อมใช้งาน
  • D: กระบวนการนี้อยู่ในสถานะพักเครื่องต่อเนื่อง กำลังใช้การเรียกระบบบล็อกและไม่สามารถดำเนินการต่อได้จนกว่าการเรียกของระบบจะเสร็จสิ้น ต่างจากสถานะ “สลีป” กระบวนการในสถานะนี้จะไม่ตอบสนองต่อสัญญาณจนกว่าการเรียกของระบบจะเสร็จสิ้นและการดำเนินการได้กลับสู่กระบวนการ
  • T: กระบวนการสิ้นสุดลง (หยุด) เนื่องจากได้รับสัญญาณ SIGSTOP มันจะตอบสนองต่อสัญญาณ SIGKILL หรือ SIGCONT เท่านั้น ซึ่งอาจฆ่ากระบวนการหรือสั่งให้ดำเนินการต่อตามลำดับ นี่คือสิ่งที่เกิดขึ้นเมื่อคุณสลับจากงานพื้นหน้า ( fg ) เป็นพื้นหลัง ( bg)
  • Z: กระบวนการซอมบี้ เมื่อกระบวนการเสร็จสิ้น จะไม่เพียงแค่หายไป มันเพิ่มหน่วยความจำที่ใช้และลบตัวเองออกจากหน่วยความจำ แต่รายการในตารางกระบวนการและ PCB ยังคงอยู่ สถานะถูกตั้งค่าเป็น EXIT_ZOMBIE และกระบวนการหลักจะได้รับแจ้ง (โดยสัญญาณ SIGCHLD ) ว่ากระบวนการลูกเสร็จสิ้นแล้ว

โฆษณา

ในสถานะ Zombie กระบวนการหลักจะเรียกหนึ่งในตระกูล wait() ของฟังก์ชันเมื่อกระบวนการลูกถูกสร้างขึ้น จากนั้นรอการเปลี่ยนแปลงสถานะในกระบวนการย่อย กระบวนการลูกถูกหยุด ดำเนินต่อไป หรือถูกฆ่าโดยสัญญาณหรือไม่? มีการยุติโดยการทำงานผ่านความสมบูรณ์ตามธรรมชาติของรหัสหรือไม่

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

ที่เกี่ยวข้อง: วิธีเรียกใช้และควบคุมกระบวนการพื้นหลังบน Linux

อะไรเป็นสาเหตุของกระบวนการซอมบี้บน Linux?

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

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

ซอมบี้ใช้หน่วยความจำเพียงเล็กน้อย แต่โดยปกติแล้วพวกมันจะไม่สร้างปัญหา รายการในตารางกระบวนการมีขนาดเล็ก แต่จะไม่สามารถนำรหัสกระบวนการกลับมาใช้ใหม่ได้จนกว่าจะเผยแพร่ สำหรับระบบปฏิบัติการ 64 บิตนั้นไม่น่าจะเกิดปัญหาใด ๆ เนื่องจาก PCB มีขนาดใหญ่กว่ารายการตารางกระบวนการมาก

ซอมบี้จำนวนมากอาจส่งผลต่อจำนวนหน่วยความจำที่ว่างสำหรับกระบวนการอื่น หากคุณมีซอมบี้จำนวนมากขนาดนั้น แสดงว่าคุณมีปัญหาร้ายแรงกับแอปพลิเคชันหลักหรือบั๊กของระบบปฏิบัติการ

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

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

โฆษณา

ทางออกเดียวที่เชื่อถือได้คือการฆ่ากระบวนการหลัก เมื่อถูกยกเลิก โปรเซสลูกจะถูกสืบทอดโดยกระบวนการ init ซึ่งเป็นกระบวนการแรกที่รันในระบบ Linux (ID กระบวนการของมันคือ 1)

กระบวนการ init ดำเนินการทำความสะอาดซอมบี้ที่จำเป็นเป็นประจำ ดังนั้นเพื่อฆ่าพวกมัน คุณเพียงแค่ต้องฆ่ากระบวนการที่สร้างพวกมัน คำสั่ง top เป็นวิธีที่สะดวกเพื่อดูว่าคุณมีซอมบี้หรือไม่

พิมพ์ต่อไปนี้:

 สูงสุด 

ระบบนี้มีแปดกระบวนการซอมบี้ เราสามารถแสดงรายการเหล่านี้ได้โดยใช้คำสั่ง ps และไพพ์ลงใน egrep อีกครั้งที่กระบวนการซอมบี้มีสถานะเป็น "Z" และโดยปกติแล้วคุณจะเห็น "หมดอายุ"

พิมพ์ต่อไปนี้:

 ps aux | egrep "Z|หมดอายุ" 

กระบวนการซอมบี้อยู่ในรายการ

วิธีนี้เป็นวิธีที่ง่ายกว่าในการค้นหา ID กระบวนการของซอมบี้มากกว่าการเลื่อนไปมา top เรายังเห็นว่าแอปพลิเคชั่นที่เรียกว่า "badprg" ทำให้เกิดซอมบี้เหล่านี้

รหัสกระบวนการของซอมบี้ตัวแรกคือ 7641 แต่เราจำเป็นต้องค้นหา ID กระบวนการของกระบวนการหลัก เราสามารถทำได้โดยใช้ ps อีกครั้ง เราจะใช้ตัวเลือกเอาต์พุต ( -o ) เพื่อบอกให้ ps แสดงเฉพาะ ID กระบวนการของพาเรนต์ แล้วส่งต่อด้วยแฟล็ก ppid=

โฆษณา

กระบวนการที่เราต้องการค้นหาจะถูกระบุโดยใช้ตัวเลือก -p (กระบวนการ) แล้วส่งผ่าน ID กระบวนการของซอมบี้

ดังนั้นเราจึงพิมพ์คำสั่งต่อไปนี้เพื่อค้นหาข้อมูลกระบวนการสำหรับกระบวนการ 7641 แต่จะรายงานเฉพาะ ID ของกระบวนการหลักเท่านั้น:

 ps -o pid= -p 7641 

เราได้รับแจ้งว่า ID กระบวนการหลักคือ 7636 ขณะนี้เราสามารถอ้างอิงโยงได้โดยใช้ ps อีกครั้ง

เราเห็นว่ามันตรงกับชื่อของกระบวนการหลักจากก่อนหน้านี้ ในการฆ่ากระบวนการพาเรนต์ ให้ใช้ตัวเลือก SIGKILL ด้วยคำสั่ง kill ดังนี้:

 ฆ่า -SIGKILL 7636

คุณอาจต้องใช้ sudo ทั้งนี้ขึ้นอยู่กับเจ้าของกระบวนการหลัก

ซอมบี้ไม่ได้น่ากลัว…

… เว้นแต่พวกเขาจะอยู่ในฝูงใหญ่ บางอย่างไม่ต้องกังวลและการรีบูตอย่างง่ายจะล้างข้อมูลเหล่านั้น

โฆษณา

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