1 คะแนน โดย GN⁺ 3 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ไมโครเคอร์เนล ซึ่งในอดีตใช้งานจริงได้ยากเพราะโอเวอร์เฮดสูง อาจกลับมาเป็นตัวเลือกที่สมเหตุสมผลได้อีกครั้งด้วย IOMMU และหน่วยความจำที่ใช้ร่วมกันซึ่งแพร่หลายแล้วในปัจจุบัน
  • การแยกไดรเวอร์และซับซิสเต็มไว้ในพื้นที่ผู้ใช้สามารถจำกัดขอบเขตผลกระทบจากบั๊กหรือการโจมตีได้ ทำให้ ความปลอดภัย·ความน่าเชื่อถือ·ความเป็นโมดูล สูงขึ้น
  • ในช่วงทศวรรษ 1980~90 โปรเซสในพื้นที่ผู้ใช้ไม่สามารถเข้าถึงอุปกรณ์ได้โดยตรง ทำให้งานอย่างการอ่านดิสก์ทุกครั้งต้องมี system call และ context switch รวมถึงการล็อกและการคัดลอกหน่วยความจำตามมา
  • เมื่อใช้ IOMMU และคิวคำสั่งแบบใช้ร่วมกัน จะสามารถจัดการ IPC แบบอะซิงโครนัสและการเข้าถึงอุปกรณ์ได้โดยไม่ต้องมี context switch การคัดลอกข้าม address space หรือการล็อกในเส้นทางปกติ
  • สามารถนำองค์ประกอบที่มีอยู่แล้วอย่าง Xen, FreeBSD และ Linux DRM มาใช้ได้ จึงไม่จำเป็นต้องแบกรับภาระการสร้าง ไฮเปอร์ไวเซอร์และเซิร์ฟเวอร์ระบบ ขึ้นใหม่ทั้งหมดตั้งแต่ต้น

โครงสร้างของไมโครเคอร์เนลและผลของการแยกส่วน

  • ไมโครเคอร์เนล คือสถาปัตยกรรมเคอร์เนลที่รันฟังก์ชันต่าง ๆ นอกเหนือจากการจัดตารางงาน การจัดการการเข้าถึงอุปกรณ์ I/O และการสื่อสารระหว่างโปรเซส (IPC) ใน พื้นที่ผู้ใช้
  • การแยกซับซิสเต็มให้ประโยชน์ 3 อย่าง
    • ความปลอดภัย: ช่องโหว่ในไดรเวอร์ตัวเดียวอาจทำให้ผู้โจมตีได้สิทธิ์เข้าถึงเพียงซับซิสเต็มหรือไดรเวอร์นั้น แทนที่จะเข้าถึงทั้งระบบ
    • ความน่าเชื่อถือ: การล่มของซับซิสเต็มหนึ่งจะกระทบเฉพาะส่วนนั้น ไม่ใช่ทั้งระบบ
    • ความเป็นโมดูล: ลดภาระของทีมเคอร์เนล Linux ที่ต้องรวมไดรเวอร์ฮาร์ดแวร์ทั้งหมดและตรวจสอบแม้แต่การทำงานภายในของชิปแต่ละตัว
  • หาก Windows เป็นระบบไมโครเคอร์เนล บั๊กของ CrowdStrike อาจจบลงแค่ทำให้การเก็บข้อมูล telemetry ของเจ้าหน้าที่ความปลอดภัยไอทีบางส่วนหยุดทำงานเท่านั้น

ข้อจำกัดด้านประสิทธิภาพในอดีตและทางออกด้วย IOMMU

  • ไมโครเคอร์เนลในอดีตนั้น โปรเซสในพื้นที่ผู้ใช้ไม่สามารถเข้าถึงอุปกรณ์บางชนิดได้โดยตรง จึงต้องมี system call และ context switch ในทุกงาน และยังมีการล็อกกับการคัดลอกหน่วยความจำที่มีต้นทุนสูงตามมา
    • Mach ค่อย ๆ ย้ายโปรเซสในพื้นที่ผู้ใช้กลับเข้าไปในเคอร์เนลเพราะปัญหาด้านประสิทธิภาพ และสุดท้ายก็มีลักษณะใกล้เคียงเคอร์เนลแบบ monolithic ทั่วไป
  • ทุกวันนี้ PC มี IOMMU เป็นมาตรฐานมาราว 10 ปีแล้ว และเมื่อใช้ร่วมกับหน่วยความจำที่ใช้ร่วมกัน ก็สามารถ ตัด context switch ออกไปทั้งหมด ได้ในเส้นทางปกติที่มีคอร์เพียงพอ
    • หากยอมรับ latency เพิ่มขึ้นเล็กน้อย ก็แทบจะกำจัด context switch ออกไปได้เกือบทั้งหมดในภาพรวม
    • ตัวจัดตารางงานที่อิงเทคโนโลยี virtualization สามารถออกแบบให้คล้ายกับไฮเปอร์ไวเซอร์ Xen ได้
    • การเข้าถึงอุปกรณ์ I/O จะถูกจัดการโดย ฮาร์ดแวร์ IOMMU
  • IPC สามารถทำได้ด้วยการจัดสรรบัฟเฟอร์ที่ใช้ร่วมกันระหว่างโปรเซส และให้การทำ compare-and-swap แบบอะตอมมิกกับจำนวนเต็ม
    • ใช้บัฟเฟอร์ร่วมเป็น คิวคำสั่ง ในรูปแบบ ring buffer และอัปเดตตัวชี้ต้นทาง·ปลายทางแบบอะตอมมิก
    • ในเส้นทางปกติสามารถส่งข้อความแบบอะซิงโครนัสได้โดยไม่ต้องมี context switch การคัดลอกข้าม address space หรือการล็อก และเป็นวิธีที่ใช้กันอย่างแพร่หลายในไดรเวอร์ GPU ด้วย

โครงสร้างไลบรารีและการใช้โค้ดเดิม

  • ในสภาพแวดล้อมที่โปรเซสเป็น VM guest สามารถลิงก์ shared library ตอนเริ่มโปรแกรม และฟังก์ชันที่ไม่จำเป็นต้องรันในโปรเซสอื่นก็สามารถจัดการภายในเครื่องได้ตามแนวทาง exokernel
    • ทุกวันนี้ที่แอปพลิเคชันมักแจกจ่ายองค์ประกอบของระบบปฏิบัติการของตัวเองมาด้วยในลักษณะคล้าย Electron ทำให้ ไลบรารีที่ซ้ำกัน ในหน่วยความจำไม่ใช่ปัญหาใหญ่เท่าเมื่อ 30 ปีก่อน
  • โครงสร้างพื้นฐานหลักที่ต้องใช้ในการพัฒนาก็มีอยู่แล้ว
    • Xen มีฟังก์ชันส่วนใหญ่ที่จำเป็นสำหรับชั้นไฮเปอร์ไวเซอร์
    • สามารถจัดเซิร์ฟเวอร์เครือข่ายและไฟล์ซิสเต็มแบบ Mach ได้ โดยดึงโค้ดจาก FreeBSD มาใช้
    • DRM ใช้บัฟเฟอร์คำสั่งแบบอะซิงโครนัสอยู่แล้ว จึงสามารถรันซับซิสเต็มกราฟิกของ Linux ในพื้นที่ผู้ใช้ได้
    • เพื่อความสะดวก ก็สามารถจัดให้ display server และซับซิสเต็มกราฟิกรันอยู่ในโปรเซสเดียวกันได้เช่นกัน

1 ความคิดเห็น

 
GN⁺ 3 시간 전
ความคิดเห็นจาก Lobste.rs
  • เหตุผลที่ Linux รวมไดรเวอร์ทั้งหมดไว้ก็เพราะไม่มี API ที่เสถียรสำหรับเคอร์เนลโมดูลนอก tree และการมี API แบบนั้นก็ไม่ได้จำเป็นต้องใช้ไมโครเคอร์เนล

    • ไมโครเคอร์เนลเองก็ไม่ได้ป้องกัน ความไม่เสถียรของ API ภายใน ได้ เพียงแค่ย้ายให้ข้ามขอบเขตระหว่างโปรเซสเท่านั้น
      จำได้ว่าเคยเห็นคำบ่นใน LKML ว่า ต่อให้ย้ายไดรเวอร์ทั้งหมดของ Linux ไปไว้ใน user space ก็ยังทำให้การเปลี่ยน API ภายในทำได้ยากขึ้น
  • เคอร์เนลตระกูล L4 ไม่ใช่ว่าขึ้นชื่อว่าเร็วหรือ? ก็เลยสงสัยว่า Redox OS หรือ Fuchsia เป็นอย่างไรบ้าง

    • เคอร์เนล L4 อาจเร็วได้ แต่ในทางปฏิบัติดูเหมือนจะเหมาะแค่กับระบบ embedded ที่มีการกำหนดค่าตายตัวมาก
      Genode รองรับหลายเคอร์เนล แต่บน seL4 เป็นต้นนั้นประสิทธิภาพแย่จนน่าขำ เพื่อนร่วมงานเคยลองบูต Linux VM แล้วรองรับแค่ 32 บิต และแค่บูตไปได้ครึ่งทางก็ใช้เวลาหลายนาที
      ที่ Genode fork ของ NOVA microhypervisor เป็นแพลตฟอร์มหลักนั้น ก็เพราะมันใช้งานได้จริงและประสิทธิภาพก็ดีพอ
    • ถ้าดู เอกสารของ Redox ตอนประกอบ request message ก็ยังมีการทำ context switch อยู่ ซึ่งน่าจะเป็นขั้นตอนตรวจสอบความถูกต้อง
      เพราะใช้ ring buffer ถ้าฝั่งรับกำลังรันอยู่บนอีกคอร์หนึ่งแล้ว อาจไม่ต้องมี context switch ครั้งที่สอง ถ้าตีความข้อความโดยไม่มี context switch ผู้รับก็ต้องตรวจสอบข้อความเอง ซึ่งอาจทำให้พื้นผิวการโจมตีใหญ่เกินไป แต่ก็ดูเหมือนยังพอมีทางบรรเทาได้ด้วย dynamic library ที่เคอร์เนลจัดให้
      ผมไม่ใช่ผู้เชี่ยวชาญ แต่รู้สึกว่าต้นฉบับตกประเด็นสำคัญไปบางอย่าง
  • QNX เป็นที่รู้จักว่าเป็นไมโครเคอร์เนลที่เร็ว เลยสงสัยว่ามันทำอะไรได้ถูกต้อง

    • QNX ที่ผมเคยใช้ไม่ได้เร็ว
      เมื่อก่อนผมกับเพื่อนหลงใหลในความงามของไมโครเคอร์เนล โดยเฉพาะ QNX เลยเอาไปทำปัญหาประมวลผลวิดีโอบน FireWire โค้ดนั้นเรียบง่ายและสวยมาก แต่ช้ามากอย่างน่าเศร้า ตอนนั้นพอเพิ่มการรองรับการส่งแบบ isochronous ที่ใช้ DMA ให้กับไดรเวอร์ 1394 บน Linux ในเวลาราว 12 ชั่วโมง ประสิทธิภาพก็ดีขึ้นมาก และเหตุการณ์นี้ก็ทำให้ความกังขาเรื่องการใช้ Linux กับเครื่องคัดแยกเชิงแสงของบริษัทหายไปด้วย
      อุดมคติของ QNX, ไมโครเคอร์เนล และ message passing ยังยอดเยี่ยมอยู่มาก แต่ถ้าจะให้แพร่หลายจริงต้องลด ต้นทุนของการส่งข้อมูลระหว่างโปรเซส ลงอีกมาก
      ตอนนี้ผมทำเว็บแอปด้วย Elixir และได้ประโยชน์จากการแยกโปรเซสแบบที่ QNX เคยชูไว้ งานไม่ได้ต้องเน้นประสิทธิภาพแบบการประมวลผลเชิงแสงจึงไม่มีปัญหา แต่ Elixir/BEAM ก็ยังมีปัญหาเรื่องการคัดลอกข้อมูลเหมือนกัน
  • ได้ยินมาว่าแม้ Mach จะไม่ได้แยกองค์ประกอบต่าง ๆ ออกจากกันอย่างสมบูรณ์ตามแนวคิดตั้งต้น แต่มันก็ไม่ได้กลายเป็น เคอร์เนลแบบ monolithic ธรรมดา และสถาปัตยกรรมของมันก็ยังมีข้อดีอยู่
    ถ้าเป็นเบนช์มาร์กแบบรายชื่อไฟล์ POSIX คลาสสิกที่เรียก readdir() และ stat() กับทุกรายการ ไมโครเคอร์เนลก็ย่อมเสียเปรียบแน่ ๆ แต่ถ้าใช้ API แบบ batch อย่าง io_uring เพื่อลดความถี่ของ system call จุดอ่อนเรื่อง latency สูงก็อาจไม่ใช่ปัญหาใหญ่

    • งานของ Liedtke “on μ-Kernel Construction”, 1995 ชี้ว่าสาเหตุที่ Mach ช้าคือ การใช้แคชมากเกินไป หรือก็คือดีไซน์ที่เล็กไม่พอ
      Linux เองก็รับความเร็วระดับ line rate ไม่ไหวเหมือนกันถ้าต้องทำ system call ทุกครั้งต่อแพ็กเก็ตเครือข่าย การทำ batch สำคัญทั้งกับ Linux และไมโครเคอร์เนล
  • มีผู้เล่นหน้าใหม่ที่น่าสนใจในวงการนี้คือ HongMeng แต่น่าเสียดายที่เป็น ซอฟต์แวร์ปิด

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

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