เมื่อกระบวนการอยู่ในโหมดผู้ใช้สามารถถูกขัดจังหวะได้ตลอดเวลา (เปลี่ยนเป็นโหมดเคอร์เนล) เมื่อเคอร์เนลกลับสู่โหมดผู้ใช้จะตรวจสอบว่ามีสัญญาณใด ๆ ที่ค้างอยู่ (รวมถึงสัญญาณที่ใช้ในการฆ่ากระบวนการเช่นSIGTERM
และSIGKILL
) นี่หมายความว่ากระบวนการสามารถถูกฆ่าได้เมื่อกลับสู่โหมดผู้ใช้เท่านั้น
เหตุผลที่กระบวนการไม่สามารถฆ่าได้ในโหมดเคอร์เนลคืออาจทำให้โครงสร้างเคอร์เนลที่ใช้โดยกระบวนการอื่น ๆ ทั้งหมดในเครื่องเดียวกันเสียหายได้ (เช่นเดียวกับการฆ่าเธรดอาจทำให้โครงสร้างข้อมูลเสียหายที่ใช้โดยเธรดอื่นในกระบวนการเดียวกัน) .
เมื่อเคอร์เนลต้องการทำอะไรบางอย่างซึ่งอาจใช้เวลานาน (เช่นการรอไปป์ที่เขียนโดยกระบวนการอื่นหรือรอให้ฮาร์ดแวร์ทำอะไรบางอย่าง) มันจะสลีปโดยทำเครื่องหมายตัวเองว่ากำลังหลับและเรียกตัวกำหนดตารางเวลา กระบวนการ (หากไม่มีกระบวนการไม่นอนหลับมันจะเปลี่ยนเป็นกระบวนการ "จำลอง" ซึ่งบอกให้ซีพียูชะลอความเร็วลงเล็กน้อยและอยู่ในลูป - ลูปที่ไม่ทำงาน)
หากสัญญาณถูกส่งไปยังกระบวนการสลีปจะต้องทำการปลุกก่อนที่จะกลับสู่พื้นที่ผู้ใช้และประมวลผลสัญญาณที่รอดำเนินการ ที่นี่เรามีความแตกต่างระหว่างการนอนหลับหลักสองประเภท:
TASK_INTERRUPTIBLE
การนอนหลับขัดจังหวะ หากงานมีการทำเครื่องหมายด้วยธงนี้มันกำลังหลับ แต่สามารถปลุกด้วยสัญญาณ นี่หมายความว่ารหัสที่ทำเครื่องหมายว่าภารกิจกำลังหลับอยู่กำลังรอสัญญาณที่เป็นไปได้และหลังจากที่ตื่นขึ้นมาแล้วจะตรวจสอบและกลับมาจากการเรียกของระบบ หลังจากจัดการสัญญาณแล้วการเรียกของระบบสามารถเริ่มใหม่ได้โดยอัตโนมัติ (และฉันจะไม่ลงรายละเอียดเกี่ยวกับวิธีการทำงาน)
TASK_UNINTERRUPTIBLE
การนอนหลับที่ไม่หยุดชะงัก หากงานถูกทำเครื่องหมายด้วยธงนี้มันไม่ได้คาดหวังว่าจะถูกปลุกด้วยสิ่งอื่นนอกจากสิ่งที่รออยู่เพราะมันไม่สามารถเริ่มต้นใหม่ได้ง่ายหรือเพราะโปรแกรมคาดว่าการเรียกของระบบจะเป็นอะตอม นอกจากนี้ยังสามารถใช้สำหรับการนอนหลับที่รู้จักกันจะสั้นมาก
TASK_KILLABLE
(กล่าวถึงในบทความ LWN ที่เชื่อมโยงกับคำตอบของ dda) เป็นตัวแปรใหม่
นี่เป็นการตอบคำถามแรกของคุณ สำหรับคำถามที่สองของคุณ: คุณไม่สามารถหลีกเลี่ยงการสลีปที่ไม่สามารถขัดจังหวะได้มันเป็นสิ่งปกติ (เกิดขึ้นเช่นทุกครั้งที่กระบวนการอ่าน / เขียนจาก / ไปยังดิสก์); อย่างไรก็ตามพวกเขาควรจะอยู่เพียงเสี้ยววินาที หากใช้งานได้นานกว่าปกติหมายถึงปัญหาฮาร์ดแวร์ (หรือปัญหาไดรเวอร์อุปกรณ์ซึ่งมีลักษณะเหมือนกับเคอร์เนล) ซึ่งไดรเวอร์อุปกรณ์กำลังรอให้ฮาร์ดแวร์ทำอะไรบางอย่างซึ่งจะไม่เกิดขึ้น นอกจากนี้ยังอาจหมายความว่าคุณกำลังใช้ NFS และเซิร์ฟเวอร์ NFS ไม่ทำงาน (กำลังรอให้เซิร์ฟเวอร์กู้คืนคุณยังสามารถใช้ตัวเลือก "intr" เพื่อหลีกเลี่ยงปัญหา)
ในที่สุดเหตุผลที่คุณไม่สามารถกู้คืนได้คือเหตุผลเดียวกับที่เคอร์เนลรอจนกว่าจะกลับไปที่โหมดผู้ใช้เพื่อส่งสัญญาณหรือฆ่ากระบวนการ: มันอาจทำให้โครงสร้างข้อมูลของเคอร์เนลเสียหาย (รหัสที่รออยู่ในโหมดพัก เพื่อกลับสู่พื้นที่ผู้ใช้โดยที่กระบวนการสามารถถูกฆ่าได้การรอรหัสในการพักเครื่องสำรองไม่คาดว่าจะเกิดข้อผิดพลาดใด ๆ )
TASK_UNINTERUPTIBLE
สถานะเมื่อใดก็ตามที่ระบบไม่ได้อยู่ในสถานะว่างจึงบังคับให้รวบรวมข้อมูลรอส่งเมื่อผู้ใช้ระดับสูงออกจากการทำงานหรือไม่ นี่จะเป็นทองคำสำหรับแฮ็กเกอร์ที่จะดึงข้อมูลกลับสู่สถานะซอมบี้และส่งข้อมูลผ่านเครือข่ายที่ว่าง บางคนสามารถโต้แย้งว่านี่เป็นวิธีหนึ่งในการสร้างBlackdoor
พลังที่จะเข้าและออกจากระบบใด ๆ ตามที่ต้องการ ฉันเชื่ออย่างยิ่งว่าช่องโหว่นี้สามารถถูกปิดผนึกได้อย่างดีโดยกำจัด `TASK_UNINTERUPTIB