การปิดระบบของเคอร์เนล linux ทำงานอย่างไรภายใน


28

ฉันมีความคิดคร่าวๆเกี่ยวกับวิธีที่ userspace และ init-system (ไม่ว่าจะเป็น sysV / upstart / systemd แบบคลาสสิค) ทำงานเมื่อปิดระบบ (ที่สำคัญคือมีการสืบทอดคำสั่ง "หยุด!", "กรุณาหยุดตอนนี้จริงๆ", "กระบวนการที่ฉันต้องฆ่าคุณเพื่อหยุด" และรอ ... สิ่งที่เกิดขึ้น)

ฉันไม่ทราบว่าการปิดระบบทำงานอย่างไรในเคอร์เนล (ซึ่งแน่นอนว่ายังมีสิ่งที่ต้องทำอีกมากมาย)

ฉันพยายามตรวจสอบเอกสารเกี่ยวกับเคอร์เนลhttps://www.kernel.org/doc/htmldocs/และใช้เครื่องมือค้นหาเพื่อนของ NSAเพื่อให้ฉันได้เริ่มต้นค้นหาวิธีการทำงาน

ฉันค้นหาด้วย SE U + L และไม่พบสิ่งใด (ฉันมองข้ามไปหรือไม่)

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

อาจมีการเปลี่ยนแปลงเพื่อเชื่อมโยงไปยังคำอธิบายรายละเอียดเพิ่มเติม

คำตอบอาจรวมถึงการที่ระบบเรียกและสัญญาณ kernal ใดบ้าง?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c น่าจะเป็นไฟล์ x86 ที่เกี่ยวข้องกับการรีบูต (แล้วปิดการปิดระบบใช่มั้ย)

อาจพบข้อมูลโค้ดได้ที่นี่http://lxr.free-electrons.com/source/kernel/reboot.c#L176 สามารถใช้เพื่ออธิบาย

176 โมฆะ kernel_power_off (เป็นโมฆะ)
177 {
178 kernel_shutdown_prepare (SYSTEM_POWER_OFF);
179 ถ้า (pm_power_off_prepare)
180 pm_power_off_prepare ();
181 migrate_to_reboot_cpu ();
182 syscore_shutdown ();
183 pr_emerg ("ปิดไฟ \ n");
184 kmsg_dump (KMSG_DUMP_POWEROFF);
185 machine_power_off ();
186}
187 EXPORT_SYMBOL_GPL (kernel_power_off);

8
ยูนิคอร์นอาจอยู่กับคุณ
Kiwy

1
@ กีวีขอบคุณสำหรับคำแนะนำ ฉันจะยอมรับหลังจากผ่านไประยะหนึ่งเพื่อหาคำตอบที่ดีกว่าที่จะเกิดขึ้น แต่อย่างน้อยตอนนี้ก็มีคำตอบ
humanityANDpeace

ไม่ต้องขอบคุณฉันขอบคุณยูนิคอร์น!
Kiwy

โปรดทราบว่ามี / เป็นกระโดดออกจากหน้าต่างตัวเลือกshutdown(8)คือเลิกใช้ -nอย่างใดอย่างหนึ่งซึ่งผมคิดว่าในเอกสารยูนิกซ์เก่าใช้ในการอ่าน " ปิดระบบตัวเอง - หน่วยหลักคือ On Fire " ได้อย่างมีประสิทธิภาพระบบยุ่งฆ่าสวิทช์ที่ จะ / สามารถปล่อยให้บิตกระจัดกระจายไปทั่วพื้น (หรืออย่างน้อยระบบไฟล์ในสถานะที่เสียหาย) - หนึ่งภาพนี้จะใช้สำหรับระบบประเภทเฟรมหลักที่มีคนจับมือพัดลมระบายความร้อน 🕱
SlySven

คำตอบ:


26

ทรัพยากรหลักที่จะเข้าใจว่าเคอร์เนล Linux ทำงานอย่างไร:

  1. เอกสาร
  2. บทความ Linux ข่าวประจำสัปดาห์
  3. แหล่งที่มา นี่เป็นสัตว์ร้ายที่ซับซ้อนซึ่งง่ายต่อการเข้าใจผ่านLXRซึ่งเป็นตัวอ้างอิงโยง Linux ตัวแปร LXR ที่ทำงานบนlxr.linux.noนั้นยอดเยี่ยมกว่าตัวอื่น ๆ แต่มักจะไม่ทำงาน

ในกรณีนี้ฉันไม่พบสิ่งใดที่เกี่ยวข้องกับศูนย์กลางจากเอกสารหรือ LWN ดังนั้นจึงเป็น LXR

สิ่งสุดท้ายที่รหัส userland ไม่เป็นโทรสายระบบreboot มันต้องใช้เวลา 4 ข้อโต้แย้งเพื่อค้นหาSYSCALL_DEFINE4(rebootบน LXR kernel/reboot.cซึ่งนำไปสู่การ หลังจากตรวจสอบสิทธิ์ของผู้โทรและอาร์กิวเมนต์แล้วจุดเข้า syscall จะเรียกหนึ่งในหลาย ๆ ฟังก์ชั่น: kernel_restartเพื่อรีบูต, kernel_haltเพื่อหยุดบนลูปที่แน่น, kernel_poweroffเพื่อปิดระบบ, kernel_kexecเพื่อแทนที่เคอร์เนลด้วยเคอร์เนลใหม่ (ถ้าคอมไพล์) หรือhibernateเพื่อบันทึกหน่วยความจำลงดิสก์ก่อนปิดเครื่อง

kernel_restart, kernel_haltและ kernel_power_offเป็นธรรมที่คล้ายกัน:

  1. ผ่านreboot_notifier_listซึ่งเป็นรายการของ hooks ที่ส่วนประกอบของเคอร์เนลสามารถลงทะเบียนเพื่อรันโค้ดเมื่อ powerdown มีเพียงไม่กี่ไดรเวอร์เท่านั้นที่จำเป็นต้องเรียกใช้งานโค้ดในขั้นตอนนี้ซึ่งส่วนใหญ่เป็นสุนัขเฝ้าบ้าน
  2. ตั้งค่าsystem_stateตัวแปร
  3. ปิดใช้งาน ตัวช่วยสร้าง usermodeเพื่อให้แน่ใจว่าจะไม่มีการเริ่มต้นรหัสผู้ใช้อีกต่อไป (อาจมีกระบวนการที่มีอยู่ในขั้นตอนนี้)
  4. โทรdevice_shutdownเพื่อปล่อยหรือปิดอุปกรณ์ทั้งหมดในระบบ ผู้ขับขี่จำนวนมากเข้ามาในเวทีนี้
    โปรดทราบว่าระบบไฟล์ใด ๆ ที่ยังคงติดตั้งอยู่ ณ จุดนี้จะถูกยกเลิกการเมานท์อย่างมีประสิทธิภาพ ผู้เรียกของการเรียกระบบจะรับผิดชอบการถอนการต่อเชื่อมใด ๆ
  5. สำหรับการปิดเครื่องเท่านั้นหากกำหนดค่า ACPI ไว้อาจเรียกใช้รหัสเพื่อเตรียมการเข้าสู่ สถานะACPI S5 (ปิดไฟอ่อน)
  6. ในเครื่องที่มีหลายซีพียูรหัสอาจทำงานบนซีพียูใด ๆ ไม่ว่าจะเรียกใช้ระบบใด migrate_to_reboot_cpuใช้ความระมัดระวังในการสลับไปใช้ CPU ตัวใดตัวหนึ่งโดยเฉพาะและป้องกันตัวกำหนดตารางเวลาจากการส่งรหัสบน CPU อื่น ๆ หลังจากจุดนี้มีเพียง CPU เดียวเท่านั้นที่ทำงาน
  7. syscore_shutdownเรียกshutdownวิธีการในการดำเนินงาน syscore ลงทะเบียน ฉันคิดว่าส่วนใหญ่เกี่ยวกับการปิดใช้งานการขัดจังหวะ hooks ไม่กี่มีshutdownวิธี
  8. บันทึกข้อความข้อมูล - เพลงหงส์
  9. สุดท้ายไปที่ส่วนที่เหลือในบางวิธีที่เครื่องขึ้นโดยการโทรmachine_restart, หรือmachine_haltmachine_power_off

จำศีลรหัสผ่านไปตามขั้นตอนต่อไปนี้:

  1. ย้ำผ่านตะขอการจัดการพลังงาน
  2. ซิงค์ระบบไฟล์
  3. ตรึงรหัสของผู้ใช้ทั้งหมด
  4. ป้องกันไม่ให้อุปกรณ์ hotplugging
  5. ดัมพ์สถานะระบบไปยังพื้นที่สว็อป
  6. หากทุกอย่างประสบความสำเร็จจำศีลฮาร์ดแวร์ นี้สามารถเกี่ยวข้องกับการเรียกร้องkernel_restart, kernel_haltหรือkernel_power_offหรือบางวิธีการจำศีลเฉพาะแพลตฟอร์ม

machine_emergency_restartวิธีที่แตกต่างกันที่จะปิดตัวลงระบบ นี้จะเรียกโดยมายากล SysRqBสำคัญ Oสำคัญทำงานแตกต่างกัน: มันเรียกkernel_power_off

ระบบยังสามารถปิดไปที่ความหวาดกลัวเช่นข้อผิดพลาดที่ไม่สามารถกู้คืนได้ Panishing พยายามบันทึกข้อความจากนั้นรีบูทระบบ (ผ่านการเฝ้าระวังฮาร์ดแวร์หรือการรีสตาร์ทฉุกเฉิน)


+1 ขอบคุณ! @Gilles หากคุณต้องการใช้โค้ดบางอย่างที่จะเช็ด / ฆ่าเชื้อ RAM ของเครื่องเป็นขั้นตอนสุดท้ายคุณจะต้องลงทะเบียนการดำเนินการ syscore สำหรับsyscore_shutdown(เช่นที่จะแก้คำถามอื่น ๆ ของฉันunix.stackexchange.com/q/122540/24394 ) . ขั้นตอน (1) และขั้นตอน (7) ทั้งคู่อนุญาตให้ลงทะเบียนสิ่งต่าง ๆ ที่จะดำเนินการเมื่อปิดเครื่องไม่แน่ใจว่าอะไรคือสิ่งที่ + ฉันมีความประทับใจต่อคำสั่งดำเนินการของการเรียกกลับเหล่านั้นใน (1) และ (7) ฉันจะเอกสารที่คุณพูดถึง แต่ถ้าคุณรู้! ขอบคุณ!
humanityANDpeace

ฉันประหลาดใจที่คำถามนี้และคำตอบไม่มี upvotes เพิ่มเติม

2

นี่เป็นเพียงคำตอบบางส่วนและฉันขอเชิญชวนคำตอบอื่น ๆ ซึ่งอาจละเอียดและชัดเจนยิ่งขึ้น

เนื้อหาของคำตอบนี้นำมาจากkernel/reboot.cไฟล์ของเคอร์เนล 3.13 linux (ซึ่งอาจไม่ใช่การเดาคำแรกเนื่องจากชื่อไม่ใช่ shutdown.c แต่ reboot.c)

อย่างไรก็ตามในนั้นเรามีฟังก์ชั่นสามอย่างที่แสดงกระบวนการปิดระบบ

  • void kernel_halt(void) // ซึ่งลงท้ายด้วยระบบในสถานะหยุดชะงัก
  • void kernel_power_off(void) // ซึ่งลงท้ายด้วยระบบปิด
  • void kernel_restart(char *cmd) // ซึ่งจบระบบเพื่อให้รีสตาร์ท

ฟังก์ชั่นเหล่านั้นสั้นมากและสามารถวางได้อย่างสมบูรณ์ รหัสของพวกเขาแสดงให้เห็นถึงขั้นตอนที่ดีที่สุดเกี่ยวกับวิธีการปิดในเคอร์เนล (ความคิดเห็นเป็นของฉันและอาจไม่เหมาะ 100% และถูกต้องตรวจสอบตัวเองเพื่อให้แน่ใจว่ามันง่ายลอง

void kernel_halt(void)

เป็นโมฆะ kernel_halt (เป็นโมฆะ)
{
    // ขั้นตอนที่ 1 ทำ:
    // a) ฟังก์ชั่นการโทร / โทรกลับที่ลงทะเบียนเพื่อทำงานเมื่อรีบูต / ปิด
    // b) ตั้งค่า system_sate เป็น SYSTEM_HALT
    // c) หยุดการตอบโต้ userspacetool
    // d) เรียกใช้ฟังก์ชัน device_shutdown ()
    kernel_shutdown_prepare (SYSTEM_HALT);

    // ขั้นตอนที่ 2: ฉันคิดว่านี่เป็นสิ่งจำเป็นสำหรับระบบ multi-cpu
    migrate_to_reboot_cpu ();

    // ขั้นตอนที่ 3:
    // syscore_shutdown - ดำเนินการเรียกกลับหลักปิดระบบที่ลงทะเบียนทั้งหมด 
    syscore_shutdown ();

    // ข้อความที่ 4
    pr_emerg ("ระบบหยุด \ n");
    kmsg_dump (KMSG_DUMP_HALT);

    // การเรียก arch ที่เจาะจง cpu-halt-code
    machine_halt ();
}

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.