วิธีฆ่ากระบวนการซอมบี้บน Linux
เผยแพร่แล้ว: 2022-01-29โปรแกรมที่เขียนไม่ดีหรือทำงานได้ไม่ดีอาจทำให้กระบวนการซอมบี้แฝงตัวอยู่ในคอมพิวเตอร์ 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
ทั้งนี้ขึ้นอยู่กับเจ้าของกระบวนการหลัก
ซอมบี้ไม่ได้น่ากลัว…
… เว้นแต่พวกเขาจะอยู่ในฝูงใหญ่ บางอย่างไม่ต้องกังวลและการรีบูตอย่างง่ายจะล้างข้อมูลเหล่านั้น
อย่างไรก็ตาม หากคุณสังเกตเห็นว่าแอปพลิเคชั่นหรือกระบวนการมักจะวางไข่ซอมบี้ นั่นคือสิ่งที่คุณควรพิจารณา เป็นไปได้มากว่าจะเป็นเพียงแค่โปรแกรมที่เขียนอย่างไม่เป็นระเบียบ ซึ่งในกรณีนี้ อาจมีเวอร์ชันที่อัปเดตที่จะล้างข้อมูลอย่างเหมาะสมหลังจากประมวลผลย่อย