20 คะแนน โดย GN⁺ 2024-09-10 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • NT มักถูกประเมินว่าเป็นระบบปฏิบัติการที่ "ก้าวหน้ามาก" แต่ผู้เขียนก็ไม่ค่อยรู้เหตุผลนัก
    • ปลายปี 2023 ผู้เขียนได้อ่าน Inside Windows NT ฉบับพิมพ์ครั้งที่ 1 แล้วจึงตัดสินใจเปรียบเทียบ NT กับ Unix
    • นี่คือการเปรียบเทียบการออกแบบของ NT (กรกฎาคม 1993) กับระบบ Unix ในยุคนั้น (4.4BSD, Linux 1.0)
    • ในฐานะผู้เชี่ยวชาญ Unix ผู้เขียนไม่ค่อยรู้จัก NT มากนัก จึงจะอธิบายโดยเน้นที่ความแตกต่างของ NT เป็นหลัก
    • เนื้อหานี้ตั้งคำถามว่า NT ดีกว่า Unix ในจุดใด และปัจจุบันยังเป็นเช่นนั้นอยู่หรือไม่

ภารกิจ

  • ประวัติของ Unix ยาวนานกว่า NT มาก
    • การพัฒนา Unix เริ่มขึ้นในปี 1969 และเป้าหมายหลักคือการเป็นแพลตฟอร์มที่สะดวกสำหรับโปรแกรมเมอร์
    • Unix ได้แรงบันดาลใจจาก Multics แต่เหนือกว่า Multics ด้วยการมุ่งเน้นความเรียบง่าย
    • ความสามารถในการพกพาข้ามระบบและมัลติทาสกิงไม่ใช่เป้าหมายดั้งเดิมของการออกแบบ Unix: ฟีเจอร์เหล่านี้ถูกเพิ่มเข้ามาในภายหลังจาก "fork" และการคิดค้น Unix ใหม่จำนวนมากในอีกหลายปีต่อมา
  • ประวัติของ Microsoft
    • MS-DOS รุ่นแรกออกในเดือนสิงหาคม 1981 และ "Windows แบบเดิม" (เวอร์ชันที่ทำงานบน DOS) รุ่นแรกออกในเดือนพฤศจิกายน 1985
    • แม้ MS-DOS จะประสบความสำเร็จอย่างกว้างขวาง แต่ Windows เริ่มมีความสำคัญอย่างแท้จริงตั้งแต่ Windows 3.0 ในเดือนพฤษภาคม 1990
    • Windows NT ถูกวางแนวคิดขึ้นในปี 1989 และปรากฏสู่โลกด้วยการออก NT 3.1 ในเดือนกรกฎาคม 1993
  • ข้อได้เปรียบของ Microsoft
    • การออกแบบ NT เริ่มต้นช้ากว่า Unix 20 ปี ซึ่งเป็นข้อได้เปรียบสำหรับ Microsoft
    • Microsoft มีฐานผู้ใช้ขนาดใหญ่จาก MS-DOS และ Windows แบบเดิมอยู่แล้ว
    • ทีม Microsoft ที่ออกแบบ NT มีทั้งข้อมูลเชิงลึกจากการพัฒนาเหล่านี้ ประสบการณ์จากการพัฒนาระบบปฏิบัติการอื่น ๆ และการเข้าถึงเทคโนโลยีสมัยใหม่ ทำให้สามารถ "เล็งไปให้สุด" ในการสร้าง NT ได้

เคอร์เนล

  • Unix ถูกนำไปใช้งานเป็นโมโนลิธิกเคอร์เนลเกือบทั้งหมด ยกเว้นบางกรณีอย่าง Minix หรือ GNU Hurd และเปิดเผยชุด system call สำหรับโต้ตอบกับฟังก์ชันที่ระบบปฏิบัติการมีให้
  • ในทางกลับกัน NT อยู่กึ่งกลางระหว่างโมโนลิธิกเคอร์เนลกับไมโครเคอร์เนล: คอมโพเนนต์สิทธิพิเศษอย่าง executive แสดงตัวเองต่อ subsystems ใน user space ในรูปของชุดคอมโพเนนต์แบบโมดูลาร์
  • subsystems ใน user space คือโปรเซสพิเศษที่ทำหน้าที่ "แปลง" API ที่แอปพลิเคชันใช้ (POSIX, OS/2 ฯลฯ) ให้เป็น executive system call
  • หนึ่งในส่วนสำคัญของ NT executive คือ HAL ซึ่งให้ primitive abstraction สำหรับเข้าถึงฮาร์ดแวร์ของเครื่อง และทำหน้าที่เป็นรากฐานให้กับส่วนที่เหลือของเคอร์เนล
    • เลเยอร์นี้คือหัวใจสำคัญที่ทำให้ NT สามารถทำงานได้บนสถาปัตยกรรมหลากหลาย รวมถึง i386, Alpha และ PowerPC
    • Unix ในเวลานั้นยังผูกติดกับสถาปัตยกรรมเฉพาะ: แนวคิดของ Unix ย้ายข้ามระบบได้ แต่ตัว implementation ยังไม่ใช่
    • เดิม SunOS รองรับเฉพาะ Motorola 68000, 386BSD เป็นการพอร์ต BSD มายังสถาปัตยกรรม Intel ครั้งแรก และ IRIX ก็เป็น Unix สายพันธุ์หนึ่งสำหรับเวิร์กสเตชัน MIPS ของ Silicon Graphics
  • อีกส่วนสำคัญของ NT executive คือการรองรับระบบมัลติโปรเซสซิงและเคอร์เนลแบบ preemptive
    • ในเคอร์เนลมีระดับ interrupt หลายระดับ (ในศัพท์ของ BSD เรียกว่า SPL) เพื่อกำหนดว่าอะไรสามารถขัดจังหวะอะไรได้ แต่สิ่งที่สำคัญกว่าคือเคอร์เนลเธรดสามารถถูก preempt โดยเคอร์เนลเธรดอื่นได้
    • ปัจจุบันระบบ Unix สมรรถนะสูงทั้งหมดทำแบบนี้ แต่ Unix จำนวนมากไม่ได้เริ่มต้นมาเช่นนั้น
    • ระบบเหล่านี้เริ่มจากเคอร์เนลที่ไม่รองรับทั้ง preemption และมัลติโปรเซสซิง จากนั้นจึงเพิ่มการรองรับมัลติโปรเซสซิงใน user space แล้วค่อยเพิ่ม kernel preemption
    • ขั้นตอนสุดท้ายเป็นขั้นตอนที่ยากที่สุด และมหากาพย์ FreeBSD 5.0 ก็แสดงให้เห็นถึงความท้าทายนั้น
    • ดังนั้นจึงน่าสนใจที่ NT เริ่มต้นมาด้วยรากฐานที่ถูกต้องตั้งแต่แรก

อ็อบเจ็กต์

  • NT เป็นเคอร์เนลเชิงวัตถุ
    • คุณอาจคิดว่า Unix ก็เป็นเช่นนั้น: โปรเซสถูกนิยามด้วย struct และ implementation ของไฟล์ซิสเต็มก็จัดการกับ vnode ("virtual node" อย่าสับสนกับ inode)
    • แต่สิ่งนี้ไม่เหมือนกับที่ NT ทำเสียทีเดียว: NT บังคับให้อ็อบเจ็กต์ทุกชนิดเหล่านี้มีตัวแทนแบบร่วมกันภายในระบบ
  • อาจสงสัยว่าจะสร้าง abstraction ที่มีความหมายให้กับสิ่งที่ต่างกันมากอย่างโปรเซสกับ file handle ได้อย่างไร
  • ในทางปฏิบัติทำไม่ได้ทั้งหมด แต่ NT บังคับให้สิ่งเหล่านี้ทั้งหมดสืบทอดจากชนิดอ็อบเจ็กต์ร่วมกัน และน่าแปลกที่มันให้คุณสมบัติที่ดีบางอย่าง
  • การควบคุมการเข้าถึงแบบรวมศูนย์
    • อ็อบเจ็กต์ถูกสร้างได้โดย object manager เท่านั้น จึงมีจุดเดียวของโค้ดสำหรับบังคับใช้นโยบาย
    • ความหมายอย่างการตรวจสอบสิทธิ์สามารถถูกกำหนดไว้เพียงจุดเดียวและบังคับใช้อย่างสม่ำเสมอทั่วทั้งระบบ ซึ่งทรงพลังมาก
    • NetBSD ก็สรุปว่าแนวคิดนี้ดีเช่นกัน แต่ต้องรอถึงปี 2001 จึงได้เฟรมเวิร์ก Kernel Authorization (kauth)
  • ID ร่วมกัน
    • อ็อบเจ็กต์มี ID และทั้งหมดถูกแสดงอยู่ในต้นไม้เดียว
    • นี่หมายความว่ามี namespace ที่เป็นเอกลักษณ์สำหรับอ็อบเจ็กต์ทุกชนิด ไม่ว่าจะเป็นโปรเซส file handle หรือ pipe
    • อ็อบเจ็กต์ในต้นไม้สามารถระบุที่อยู่ได้ด้วยชื่อ (path) และส่วนต่าง ๆ ของต้นไม้อาจเป็นของ subsystem ที่ต่างกัน
    • ตัวอย่างเช่น ส่วนหนึ่งของต้นไม้อาจแทนไฟล์ซิสเต็มที่ถูก mount อยู่ ดังนั้นเมื่อไล่ไปถึงโหนดรากของ subtree นั้นแล้ว ไฟล์ซิสเต็มก็จะเป็นผู้ resolve ส่วนที่เหลือของ path
    • สิ่งนี้คล้ายกับเลเยอร์ VFS ของระบบ Unix แต่ VFS จัดการเฉพาะไฟล์ซิสเต็ม ขณะที่ object tree ครอบคลุม อ็อบเจ็กต์ในเคอร์เนลทุกชนิด
    • Unix พยายามยัดอ็อบเจ็กต์ที่ไม่ใช่ไฟล์ลงในไฟล์ซิสเต็มผ่าน /proc/, /sys/ เป็นต้น แต่เมื่อเทียบกับสิ่งที่ NT มีให้แล้ว มันให้ความรู้สึกเหมือนเป็นการแก้ทีหลัง
  • การจัดการอีเวนต์แบบบูรณาการ
    • อ็อบเจ็กต์ทุกชนิดมีสถานะ signaled แต่ความหมายของมันแตกต่างกันไปตามชนิดของอ็อบเจ็กต์
    • ตัวอย่างเช่น อ็อบเจ็กต์โปรเซสจะเปลี่ยนเป็นสถานะ signaled เมื่อโปรเซสสิ้นสุดลง และอ็อบเจ็กต์ file handle จะเปลี่ยนเป็นสถานะ signaled เมื่อคำขอ I/O เสร็จสิ้น
    • สิ่งนี้ทำให้การเขียนโค้ดแบบอิงอีเวนต์ (โค้ด async) ใน user space ง่ายมาก เพราะ system call แบบ wait เพียงแบบเดียวก็สามารถรอให้อ็อบเจ็กต์กลุ่มหนึ่งเปลี่ยนสถานะได้
    • ในระบบ Unix การรอทั้ง I/O และการจบของโปรเซสพร้อมกันเป็นเรื่องน่าปวดหัว
  • อ็อบเจ็กต์เป็นองค์ประกอบเฉพาะของ NT และไม่ได้ทำให้เป็นนามธรรมร่วมได้ดีกับทุก API ที่ NT ต้องการรองรับ
    • ตัวอย่างเช่น POSIX subsystem: POSIX ไม่มีแนวคิดเรื่องอ็อบเจ็กต์แบบ NT แต่ NT ก็ต้องให้ความเข้ากันได้บางระดับกับแอปพลิเคชัน POSIX
    • ด้วยเหตุนี้ ขณะที่ POSIX subsystem จัดสรรอ็อบเจ็กต์จาก executive มันก็ต้องเก็บบันทึกของตัวเองเพื่อแทนเอนทิตีแบบ POSIX และทำการแปลงเชิงตรรกะระหว่างสองเอนทิตีนี้ทันที
    • ในทางกลับกัน Win32 subsystem ส่งมอบอ็อบเจ็กต์ให้ client โดยตรงโดยไม่ต้องมีตัวกลาง

โปรเซส

  • โปรเซสเป็นอ็อบเจ็กต์ที่ NT และ Unix มีร่วมกัน แต่ไม่ได้เหมือนกันทั้งหมด
    • ใน Unix โปรเซสจะแสดงเป็นต้นไม้ โดยแต่ละโปรเซสมีโปรเซสแม่ และโปรเซสหนึ่ง ๆ สามารถมีโปรเซสลูกได้ตั้งแต่ 0 ตัวขึ้นไป
    • แต่ใน NT ไม่มีความสัมพันธ์แบบนั้น: โปรเซสสามารถ "สืบทอด" ทรัพยากรจากตัวสร้างได้ แต่หลังจากถูกสร้างแล้วจะเป็นเอนทิตีอิสระ
  • ในช่วงที่ NT ถูกออกแบบ เธรดยังไม่ใช่เรื่องแพร่หลาย:
    • Mach เป็นเคอร์เนลลักษณะ Unix ตัวแรกที่รวมเธรดเข้าไว้ในปี 1985
    • นั่นหมายความว่า Unix อื่น ๆ ต้องนำแนวคิดนี้มาใช้ภายหลังและดัดแปลงให้เข้ากับการออกแบบเดิม
    • Linux เลือกในรีลีส 2.0 เมื่อเดือนมิถุนายน 1996 ที่จะแสดงเธรดเป็นโปรเซสซึ่งแต่ละตัวมี PID ของตัวเอง ส่วน NetBSD ต้องรอจนถึงรีลีส 2.0 ในปี 2004 จึงมีเธรดที่แสดงเป็นเอนทิตีแยกจากโปรเซส
    • ต่างจาก Unix, NT เลือกสนับสนุนเธรดมาตั้งแต่แรก เพราะรู้ว่าเธรดเป็นสิ่งจำเป็นสำหรับการประมวลผลสมรรถนะสูงบนเครื่อง SMP
  • NT ไม่มี signal ในความหมายแบบ Unix ดั้งเดิม
    • แต่มี alerts แทน ซึ่งอาจเป็นได้ทั้งโหมดเคอร์เนลและโหมดผู้ใช้
    • การแจ้งเตือนโหมดผู้ใช้ต้องรอเหมือนกับอ็อบเจ็กต์อื่น ๆ และการแจ้งเตือนโหมดเคอร์เนลจะมองไม่เห็นสำหรับโปรเซส
    • ระบบย่อย POSIX ใช้การแจ้งเตือนโหมดเคอร์เนลเพื่อจำลอง signal
    • signal มักถูกเรียกว่าเป็นตำหนิของ Unix เพราะวิธีที่มันขัดจังหวะการทำงานของโปรเซส: การจัดการ signal ให้ถูกต้องเป็นงานที่ยากมาก ดังนั้นทางเลือกของ NT จึงดูสง่างามกว่า
  • พัฒนาการที่น่าสนใจล่าสุดใน NT คือการนำ pico process เข้ามาใช้
    • ก่อนเพิ่มความสามารถนี้ โปรเซสของ NT ค่อนข้างหนัก: โปรเซสใหม่จะได้รับชุดไลบรารีรันไทม์ของ NT ที่แมปเข้ามาในแอดเดรสสเปซตั้งแต่เริ่มต้น
    • ใน pico process ตัวโปรเซสมีความผูกพันกับสถาปัตยกรรม Windows เพียงเล็กน้อย และถูกใช้ในการทำโปรเซสที่เข้ากันได้กับ Linux ใน WSL 1
    • ในบางแง่ pico process ใกล้เคียงกับโปรเซสแบบ Unix มากกว่าโปรเซส Windows พื้นฐาน แต่จากการย้ายไป WSL 2 ทำให้มันไม่ค่อยถูกใช้อีกแล้ว แม้จะมีมาตั้งแต่เดือนสิงหาคม 2016
  • แม้จะมีการตำหนิประเด็นความปลอดภัยของ Windows อยู่มาก แต่ NT เริ่มต้นมาพร้อมการออกแบบความปลอดภัยที่ก้าวหน้าสำหรับมาตรฐานอินเทอร์เน็ตยุคแรก ๆ โดยระบบทำงานในลักษณะ capability-based โดยพื้นฐาน
    • โปรเซสผู้ใช้ตัวแรกที่เริ่มหลังการล็อกอินจะได้รับ access token จากเคอร์เนล ซึ่งแสดงสิทธิ์ของเซสชันผู้ใช้ และโปรเซสกับโปรเซสย่อยต้องส่งโทเคนนี้ให้เคอร์เนลเพื่อยืนยันสิทธิ์
    • สิ่งนี้ต่างจาก Unix ที่โปรเซสมีเพียงตัวระบุ และเคอร์เนลต้องติดตามในตารางโปรเซสว่าแต่ละโปรเซสทำอะไรได้บ้าง

ความเข้ากันได้

  • เป้าหมายหลักของ NT คือเข้ากันได้กับแอปพลิเคชันที่เขียนมาสำหรับ Windows รุ่นเก่า, DOS, OS/2 และ POSIX
    • เหตุผลหนึ่งเป็นเรื่องทางเทคนิค เพราะสิ่งนี้บังคับให้ระบบต้องมีการออกแบบที่สง่างาม
    • อีกเหตุผลหนึ่งเป็นเรื่องทางการเมือง เพราะ NT ถูกพัฒนาร่วมกับ IBM และแม้ท้ายที่สุด NT จะกลายเป็น Windows แต่ก็ จำเป็นต้อง รองรับแอปพลิเคชัน OS/2
  • ความจำเป็นด้านความเข้ากันได้นี้ทำให้การออกแบบของ NT แตกต่างจาก Unix อย่างมาก
    • ใน Unix แอปพลิเคชันใน user space สื่อสารกับเคอร์เนลโดยตรงผ่านอินเทอร์เฟซ system call และอินเทอร์เฟซนี้ก็คืออินเทอร์เฟซแบบ Unix
    • C library ทำหน้าที่เป็นตัวเชื่อมสำหรับเรียกเคอร์เนล และแอปพลิเคชันไม่ได้รัน system call โดยตรง แต่รายละเอียดนี้เป็นเพียงเรื่องเล็กน้อย
  • ใน NT แอปพลิเคชัน ไม่ได้ สื่อสารกับ executive (เคอร์เนล) โดยตรง
    • แต่แอปพลิเคชันแต่ละตัวจะสื่อสารกับ subsystem ที่ได้รับการป้องกันตัวใดตัวหนึ่ง ซึ่ง subsystem เหล่านี้ทำหน้าที่ติดตั้งใช้งาน API ของระบบปฏิบัติการต่าง ๆ ที่ NT ต้องการให้เข้ากันได้
    • subsystem เหล่านี้ถูกติดตั้งเป็นเซิร์ฟเวอร์ใน user space (ไม่ได้อยู่ภายใน "microkernel" ของ NT)
    • การรองรับแอปพลิเคชัน Windows มีให้ผ่าน Win32 server ซึ่งพิเศษเพราะเป็นเซิร์ฟเวอร์เพียงตัวเดียวที่ผู้ใช้มองเห็นได้โดยตรง: มันควบคุมโปรแกรมคอนโซลและเทอร์มินัล DOS และมีสิทธิพิเศษบางอย่างด้วยเหตุผลด้านประสิทธิภาพ
  • เมื่อเทียบกับ Unix แบบดั้งเดิม BSD และ Linux มีเคอร์เนลแบบ monolithic ดังนั้นการออกแบบของ NT จึงต่างออกไปมาก
    • เคอร์เนลเหล่านี้เปิดเผยอินเทอร์เฟซ system call ที่แอปพลิเคชันใน user space ใช้เพื่อโต้ตอบกับระบบโดยตรง
    • อย่างไรก็ตาม BSD รองรับการรัน ไบนารี ทางเลือกภายในเคอร์เนลแบบ monolithic มายาวนาน: วิธีทำงานคือเปิดเผยตาราง system call ที่ต่างออกไปให้กับ user space ตามไบนารีที่กำลังรัน จากนั้นแปลง system call "ภายนอก" เหล่านั้นให้เป็นสิ่งที่เคอร์เนลเข้าใจ
    • Linux ก็มีการรองรับแบบจำกัดสำหรับสิ่งนี้ผ่าน personalities เช่นกัน
  • แม้แนวทางของ BSD จะแตกต่างจากวิธีที่ NT รองรับระบบอื่นมาก แต่ WSL 1 กลับคล้ายกันมาก และไม่ใช่ subsystem ตามคำจำกัดความดั้งเดิม
    • ใน WSL 1 เคอร์เนล NT จะทำเครื่องหมายโปรเซส Linux เป็น pico process และจากจุดนั้นก็เปิดเผยอินเทอร์เฟซ system call แบบอื่นออกมา
    • ภายในเคอร์เนล NT system call ที่เกี่ยวข้องกับ Linux เหล่านั้นจะถูกแปลงเป็นการทำงานของ NT และให้บริการภายในเคอร์เนลเดียวกัน คล้ายกับ Linux compatibility ของ BSD
    • ปัญหาเดียวคือ NT ไม่ใช่ Unix ดังนั้นการ "จำลอง" Linux จึงทำได้ยากและช้ากว่าสิ่งที่ BSD สามารถให้ได้มาก
    • น่าเสียดายที่ WSL 2 สูญเสียแก่นของการออกแบบนี้ไปและหันไปใช้การออกแบบแบบ VM เต็มรูปแบบ
  • รายละเอียดที่น่าสนใจของการออกแบบ NT
    • เป้าหมายของการออกแบบ NT คือเปิดทางให้มีการเปลี่ยนทาง I/O ระหว่าง subsystem ได้อย่างราบรื่นจากเชลล์เดียว
    • subsystem จะถูกเปิดเผยให้แอปพลิเคชันผ่าน ports ซึ่งเป็นอ็อบเจ็กต์ของ NT และคล้ายกับวิธีที่ Mach ใช้ให้โปรเซสกับเซิร์ฟเวอร์สื่อสารกัน

หน่วยความจำเสมือน

  • NT เช่นเดียวกับ Unix พึ่งพา Memory Management Unit(MMU) ที่มีการแบ่งหน้าเพื่อให้การปกป้องระหว่างโปรเซสและมอบหน่วยความจำเสมือน
    • การแบ่งหน้าสำหรับโปรเซสใน user space เป็นกลไกทั่วไปที่ทำให้มีแอดเดรสสเปซใหญ่กว่าปริมาณหน่วยความจำจริงของเครื่อง
    • อย่างไรก็ตาม สิ่งหนึ่งที่ทำให้ NT ล้ำหน้ากว่าระบบ Unix ร่วมยุคคือเคอร์เนลเองก็สามารถถูกเพจออกไปยังดิสก์ได้
    • หากทั้งเคอร์เนลสามารถถูกเพจได้ทั้งหมด ก็อาจเกิดสถานการณ์ที่ต้องแก้ kernel page fault ซึ่งต้องใช้โค้ดของไดรเวอร์ระบบไฟล์ที่ถูกเพจออกไปแล้ว แต่ส่วนสำคัญของเคอร์เนลนั้นเพจได้
    • ทุกวันนี้สิ่งนี้อาจไม่ได้น่าสนใจเป็นพิเศษ เพราะเคอร์เนลมีขนาดเล็กเมื่อเทียบกับหน่วยความจำที่ติดตั้งทั่วไปในเครื่อง แต่ในอดีตทุกไบต์มีค่า จึงสร้างความแตกต่างได้มาก
  • ทุกวันนี้เราอาจมองว่าหน่วยความจำเสมือนและการแบ่งหน้าเป็นเรื่องปกติ แต่ตอนที่ NT ถูกออกแบบ นี่เป็นหัวข้อวิจัยขนาดใหญ่
    • การติดตั้งใช้งาน Unix ก่อนหน้านั้นมีแคชหน่วยความจำแยกกันสำหรับระบบไฟล์และหน่วยความจำเสมือน และต้องรอถึงปี 1987 กว่า SunOS จะติดตั้งสถาปัตยกรรมหน่วยความจำเสมือนแบบรวมเพื่อลดโอเวอร์เฮดของการออกแบบเดิม
    • ในทางกลับกัน NT เริ่มต้นมาพร้อมสถาปัตยกรรมหน่วยความจำแบบรวมตั้งแต่แรก
    • อาจพูดได้ว่าการทำเช่นนี้ง่ายขึ้นเพราะมีข้อมูลเชิงลึกเกี่ยวกับความไม่มีประสิทธิภาพที่พบใน Unix และได้เห็นโซลูชันที่ SunOS ติดตั้งไว้ก่อนที่การออกแบบ NT จะเริ่มขึ้น
    • แต่ก็ควรสังเกตว่าสิ่งนี้ทำให้ NT "ก้าวหน้ากว่า" ระบบปฏิบัติการอื่นจำนวนมากในเวลานั้น และระบบอื่น ๆ ก็เพิ่งตามทันในปี 2002 ด้วยการติดตั้ง Unified Buffer Cache(UBC) ของ NetBSD 1.6
  • ความแตกต่างที่น่าสนใจระหว่าง NT กับ Unix คือวิธีจัดการและแสดงหน่วยความจำที่ใช้ร่วมกัน
    • ใน NT ส่วนของหน่วยความจำที่ใช้ร่วมกันเป็นอ็อบเจ็กต์ จึงได้รับการตรวจสอบความถูกต้องของการเข้าถึงแบบเดียวกับอ็อบเจ็กต์อื่นทั้งหมด
    • นอกจากนี้ยังเป็นส่วนหนึ่งของต้นไม้อ็อบเจ็กต์เดียว จึงสามารถระบุที่อยู่ได้ในลักษณะเดียวกับอ็อบเจ็กต์อื่นทั้งหมด
    • ใน Unix ความสามารถนี้เป็นสิ่งที่ถูกยึดติดเพิ่มเข้าไปภายหลัง: อ็อบเจ็กต์หน่วยความจำที่ใช้ร่วมกันมีเนมสเปซแยก มี API แยกจากเอนทิตีอื่นทั้งหมด ดังนั้นสิทธิ์แบบทั่วไปจึงไม่ถูกนำมาใช้

ระบบย่อย I/O

  • Unix รุ่นแรก ๆ รองรับระบบไฟล์ได้เพียงระบบเดียว
    • ตัวอย่างเช่น BSD ได้รับ abstraction ของ Virtual File System(VFS) เพื่อรองรับมากกว่า UFS ก็ต้องรอถึง 4.3BSD ในเดือนเมษายน 1990
    • ในทางกลับกัน NT เริ่มต้นจากการออกแบบที่รองรับหลายระบบไฟล์
  • เพื่อรองรับหลายระบบไฟล์ เคอร์เนลจำเป็นต้องเปิดเผย namespace ของระบบเหล่านั้นไม่ทางใดก็ทางหนึ่ง
    • Unix รวมระบบไฟล์เข้าด้วยกันในลำดับชั้นไฟล์เดียวผ่าน mount point: เลเยอร์ VFS มีกลไกสำหรับระบุโหนดที่สอดคล้องกับรากของระบบไฟล์ และเปลี่ยนเส้นทางคำขอไปยังไดรเวอร์ระบบไฟล์นั้นเมื่อมีการไล่ตาม path
    • NT มีการออกแบบคล้ายกัน แม้ในส่วนติดต่อผู้ใช้มาตรฐานระบบไฟล์จะปรากฏเป็นไดรฟ์ที่แยกจากกัน: ภายในแล้ว executive จะแทนระบบไฟล์เป็นอ็อบเจ็กต์ใน object tree และแต่ละอ็อบเจ็กต์มีหน้าที่แยกวิเคราะห์ส่วนที่เหลือของ path
    • จากนั้นอ็อบเจ็กต์ระบบไฟล์เหล่านั้นจะถูกแมปกลับเป็นไดรฟ์ DOS เพื่อให้เข้าถึงได้จาก user space
    • ไดรฟ์ DOS เองก็เป็นอ็อบเจ็กต์ภายใต้ subtree แยกต่างหากที่ทำหน้าที่ redirect I/O ไปยังระบบไฟล์ที่อ้างถึง
  • ในท้ายที่สุด NT เปิดตัวพร้อมกับ NTFS
    • แม้ NTFS จะชอบถูกโจมตีว่าให้ประสิทธิภาพไม่ดี (ซึ่งเป็นข้อกล่าวหาที่ไม่ถูกต้อง) แต่มันเป็นระบบไฟล์ที่ก้าวหน้ามากสำหรับยุคนั้น
    • ระบบย่อย I/O ของ NT เมื่อทำงานร่วมกับ NTFS ได้มอบการอ้างแอดเดรสแบบ 64 บิต, journaling และแม้กระทั่งชื่อไฟล์แบบ Unicode
    • Linux ยังไม่ได้รองรับไฟล์ 64 บิตจนถึงช่วงปลายทศวรรษ 1990 และยังไม่มี journaling จนกว่า ext3 จะเปิดตัวในปี 2001
    • Soft updates ซึ่งเป็นกลไกด้าน fault tolerance ทางเลือก เพิ่งปรากฏใน FreeBSD ในปี 1998
    • Unix แทนชื่อไฟล์เป็นอาร์เรย์ไบต์ที่ลงท้ายด้วย null ไม่ใช่ Unicode
  • ฟีเจอร์อื่นที่มีมาในตอนเปิดตัว NT ได้แก่ disk striping และ mirroring (สิ่งที่ปัจจุบันเรียกว่า RAID) รวมถึงการ hot-plug อุปกรณ์
    • ฟีเจอร์เหล่านี้ไม่ใช่ของใหม่ เพราะ SunOS มี RAID รองรับมาตั้งแต่ต้นทศวรรษ 1990 แต่จุดที่น่าสนใจคือทั้งหมดนี้ถูกพิจารณาไว้เป็นส่วนหนึ่งของการออกแบบตั้งแต่แรก
    • ในระดับที่สูงขึ้น สิ่งที่ทำให้ระบบย่อย I/O ของ NT ก้าวหน้ากว่า Unix มากคืออินเทอร์เฟซของมันมีลักษณะเป็น asynchronous โดยเนื้อแท้ และเป็นเช่นนั้นมาตั้งแต่ต้น
    • เพื่อให้เห็นภาพ FreeBSD เพิ่งมีการรองรับ aio(7) ใน FreeBSD 3.0 ปี 1998 และ Linux ก็เพิ่งมีใน Linux 2.5 ปี 2002
    • แม้ระบบ Unix จะมีการรองรับ asynchronous I/O มานานกว่า 20 ปีแล้ว แต่มันก็ยังไม่ถูกใช้อย่างแพร่หลาย: แทบไม่มีใครรู้จัก API เหล่านี้ แอปพลิเคชันส่วนใหญ่ก็ไม่ใช้ และประสิทธิภาพก็ไม่ดี
    • io_uring ของ Linux เป็นส่วนเสริมที่ค่อนข้างใหม่เพื่อปรับปรุง asynchronous I/O แต่ก็เป็นสาเหตุสำคัญของช่องโหว่ด้านความปลอดภัยและยังไม่ถูกใช้อย่างแพร่หลาย

เครือข่าย

  • ทุกวันนี้อินเทอร์เน็ตมีอยู่ทุกหนแห่ง แต่ตอนที่ NT ถูกออกแบบนั้นยังไม่เป็นเช่นนั้น
    • หากมองย้อนกลับไปใน ecosystem ของ Microsoft, DOS 3.1 (1987) มีพื้นฐานสำหรับการแชร์ไฟล์บนระบบไฟล์ FAT แล้ว แต่ตัว "OS" เองไม่ได้มีความสามารถด้านเครือข่าย: มีผลิตภัณฑ์แยกต่างหากชื่อ Microsoft Networks(MS-NET) ที่ทำหน้าที่นี้
    • Windows 3.0 (1990) มีการรองรับ NetBIOS ที่เปิดให้มีการแชร์พรินเตอร์และไฟล์พื้นฐานบนเครือข่ายท้องถิ่น แต่ยังไม่พบการรองรับ TCP/IP
  • ในทางกลับกัน Unix คืออินเทอร์เน็ตนั่นเอง: โปรโตคอลอินเทอร์เน็ตพื้นฐานทั้งหมดถูกเขียนบน Unix และเขียนขึ้นเพื่อ Unix
    • ระหว่างการออกแบบ NT การคำนึงถึงการรองรับเครือข่ายที่ดีจึงเป็นเรื่องสำคัญ และท้ายที่สุด NT ก็เปิดตัวพร้อมความสามารถด้านเครือข่าย
    • ผลลัพธ์คือ NT รองรับทั้งโปรโตคอลอินเทอร์เน็ตและโปรโตคอล LAN แบบดั้งเดิมที่ใช้ในสภาพแวดล้อม Microsoft เดิม ซึ่งทำให้ NT เหนือกว่า Unix ในสภาพแวดล้อมองค์กร
  • ตัวอย่างหนึ่งคือ network domain ของ NT
    • ใน Unix ผู้ดูแลเครือข่ายโดยทั่วไปมักซิงก์บัญชีผู้ใช้ระหว่างเครื่องต่าง ๆ ด้วยตนเอง
    • ระบบอย่าง SunOS อาจใช้โปรโตคอลไดเรกทอรี X.500 (1988) และ Kerberos (ทศวรรษ 1980) สำหรับการยืนยันตัวตนผู้ใช้ แต่เทคโนโลยีเหล่านี้ไม่ได้เรียบง่ายเป็นพิเศษ
    • แทนที่จะเป็นเช่นนั้น NT ให้ domain ที่รวมฟังก์ชันไดเรกทอรีและการยืนยันตัวตนมาตั้งแต่เริ่ม ซึ่งดูเหมือนจะเป็นสิ่งที่ "ชนะ" ในเครือข่ายองค์กร เพราะตั้งค่าได้ง่ายกว่ามากและมีมาในระบบอยู่แล้ว
  • เป้าหมายของการซิงก์บัญชีผู้ใช้คือการแชร์ทรัพยากรระหว่างเครื่อง โดยหลักคือไฟล์ และเมื่อทำเช่นนี้ วิธีการแสดงสิทธิ์ก็มีความสำคัญ
    • เป็นเวลานาน Unix ให้เพียงชุดสิทธิ์อ่าน/เขียน/รันอย่างง่ายสำหรับแต่ละไฟล์
    • ในทางกลับกัน NT มาพร้อม ACL ขั้นสูงตั้งแต่แรก ซึ่งยังคงเป็นจุดเจ็บปวดของ Unix มาจนถึงทุกวันนี้
    • แม้ตอนนี้ Linux และ BSD ก็มี ACL แล้ว แต่ส่วนติดต่อระหว่างระบบไม่สอดคล้องกัน และให้ความรู้สึกเหมือนเป็นส่วนเสริมที่แปลกแยกกับการออกแบบระบบ
    • ใน NT, ACL ทำงานในระดับอ็อบเจ็กต์ จึงถูกนำไปใช้อย่างสอดคล้องกับความสามารถทั้งหมดของเคอร์เนล
  • เมื่อพูดถึงการแชร์ไฟล์ ก็ต้องพูดถึง network file system
    • ในโลก Unix นั้นโดยพฤตินัยระบบไฟล์คือ NFS และใน NT คือ SMB
    • SMB สืบทอดมาจาก MS-NET และ LAN Manager และถูกทำให้เป็นจริงในเคอร์เนลผ่านคอมโพเนนต์ที่เรียกว่า redirector
    • โดยเนื้อแท้แล้ว redirector ก็เป็นอีกระบบไฟล์หนึ่งที่ "เรียบง่าย" ทำหน้าที่ดักจับการทำงานกับไฟล์และส่งต่อผ่านเครือข่าย เช่นเดียวกับที่ NFS เป็นอยู่ใน Unix
  • protobuf และ gRPC อาจถูกใช้กันแพร่หลายจนดูเหมือนเป็นไอเดียใหม่ แต่จริง ๆ แล้วตั้งอยู่บนแนวคิดเก่า
    • ใน Unix มีการใช้ Sun RPC มาตั้งแต่ต้นทศวรรษ 1980 โดยหลักเพื่อรองรับ NFS
    • เช่นเดียวกัน NT ก็มาพร้อมการรองรับ RPC ในตัว ผ่าน DSL ของตัวเอง (ซึ่งรู้จักกันในชื่อ MIDL สำหรับระบุ interface definition และสร้างโค้ดสำหรับ remote procedure) รวมถึงความสามารถของตัวเองสำหรับการสร้าง RPC client และ server
  • ระบบ Unix ไม่ได้มุ่งเน้นอย่างหนักไปที่การรองรับไดรเวอร์ตามอำเภอใจ: โดยทั่วไปแล้วระบบ Unix มักผูกติดกับเครื่องและผู้ขายเฉพาะราย
    • ในทางกลับกัน NT พยายามจะเป็น OS สำหรับ "ทุก" เครื่อง และถูกขายโดยบริษัทซอฟต์แวร์ ดังนั้นการรองรับไดรเวอร์ที่ผู้อื่นเขียนจึงสำคัญ
    • ผลก็คือ NT มาพร้อม Network Driver Interface Specification(NDIS) ซึ่งเป็น abstraction เพื่อให้รองรับไดรเวอร์การ์ดเครือข่ายได้ง่าย
    • จนถึงทุกวันนี้ ไดรเวอร์ที่ผู้ผลิตจัดหาให้ก็ยังไม่ใช่เรื่องปกตินักบน Linux และสิ่งนี้นำไปสู่อุปกรณ์/กลไกที่น่าสนใจอย่าง ndiswrapper ซึ่งเคยได้รับความนิยมมากในช่วงต้นทศวรรษ 2000 เพราะทำให้สามารถนำไดรเวอร์ Windows สำหรับการ์ด WiFi มาใช้ซ้ำบน Linux ได้
  • สุดท้าย ความแตกต่างอีกอย่างระหว่าง NT กับ Unix อยู่ที่การทำงานของ named pipe
    • named pipe ใน Unix เป็นองค์ประกอบภายในเครื่อง: มันมอบกลไกให้สองโปรเซสบนเครื่องเดียวกันสื่อสารกันได้ผ่านชื่อไฟล์แบบถาวรบนดิสก์
    • NT ก็มีความสามารถเดียวกันนี้ แต่ named pipe สามารถทำงานผ่านเครือข่ายได้
    • หากวาง named pipe ไว้บนระบบไฟล์ที่แชร์อยู่ แอปพลิเคชันสองตัวบนคอมพิวเตอร์ต่างกันก็สามารถสื่อสารกันได้โดยไม่ต้องกังวลกับรายละเอียดด้านเครือข่าย

User-Space

  • การตั้งค่า:
    • NT รวมการตั้งค่าระบบและแอปพลิเคชันไว้ศูนย์กลางในฐานข้อมูลที่เรียกว่า Registry ทำให้หลุดพ้นจาก CONFIG.SYS, AUTOEXEC.BAT และไฟล์ INI จำนวนมากที่ใช้ใน Windows รุ่นเก่า
    • แม้สิ่งนี้จะทำให้บางคนไม่พอใจอย่างมาก แต่ท้ายที่สุดอินเทอร์เฟซการตั้งค่าแบบรวมศูนย์ก็เป็นประโยชน์ต่อทุกฝ่าย: การเขียนแอปทำได้ง่ายขึ้นเพราะมีพื้นฐานให้รองรับเพียงแบบเดียว และผู้ใช้ก็ปรับแต่งระบบได้ง่ายขึ้นเพราะมีที่ให้ตรวจดูเพียงแห่งเดียว
    • ในทางกลับกัน Unix ยังคงมีปัญหาจาก DSL หลายสิบแบบและตำแหน่งไฟล์ที่ไม่สอดคล้องกัน
    • แต่ละโปรแกรมที่รองรับไฟล์คอนฟิกก็มีไวยากรณ์ของตัวเอง และการรู้ว่าโปรแกรมอ่านจากที่ใดก็เป็นเรื่องยาก แถมยังไม่ได้มีเอกสารอธิบายไว้อย่างดีเสมอไป
    • ระบบนิเวศ Linux พยายามผลักดันแนวทางคล้าย NT ผ่าน XDG และ dconf (เดิมคือ GConf) แต่ส่วนประกอบฝั่งเดสก์ท็อปใช้เทคโนโลยีเหล่านี้แบบเฉพาะทาง ขณะที่ส่วนประกอบหลักของระบบกลับไม่รับไปใช้ จึงทิ้งความไม่สอดคล้องกันที่ยุ่งเหยิงไว้
  • การทำให้รองรับหลายภาษา:
    • Microsoft ในฐานะบริษัทขนาดใหญ่ที่นำ Windows 3.x ออกวางจำหน่ายทั่วโลกอยู่แล้ว เข้าใจว่าการแปลและปรับให้เข้าท้องถิ่นมีความสำคัญ และจึงทำให้ NT รองรับความสามารถเหล่านี้มาตั้งแต่ต้น
    • เมื่อนำไปเทียบกับ Unix ซึ่งการรองรับ UTF เริ่มปรากฏขึ้นในช่วงปลายทศวรรษ 1990 และรองรับภาษาอื่นผ่านส่วนเสริม gettext แบบเลือกติดตั้ง จะเห็นความต่างได้ชัดเจน
  • ภาษา C:
    • สิ่งหนึ่งที่ระบบ Unix อย่าง FreeBSD และ NetBSD ใฝ่ฝันกันมาระยะหนึ่งคือการคิดค้นสำเนียง C ของตนเองขึ้นมาเพื่อใช้เขียนเคอร์เนลให้ปลอดภัยยิ่งขึ้น
    • แต่แนวทางนี้ก็ไม่ไปถึงไหน ยกเว้น Linux ที่พึ่งพาส่วนขยายเฉพาะของ GCC
    • ขณะที่ Microsoft มีข้อได้เปรียบจากการเป็นเจ้าของคอมไพเลอร์ C จึงทำสิ่งนี้ได้ใน NT ที่เขียนด้วย Microsoft C
    • ตัวอย่างเช่น NT พึ่งพา Structured Exception Handling (SEH) ซึ่งเป็นความสามารถในการเพิ่ม clause try/except เพื่อจัดการข้อยกเว้นทั้งจากซอฟต์แวร์และฮาร์ดแวร์
    • คงพูดไม่ได้ว่านี่เป็นข้อได้เปรียบใหญ่โต แต่ก็เป็นความแตกต่างที่มีอยู่จริง

บทสรุป

  • NT เป็นเทคโนโลยีที่ก้าวล้ำในช่วงเวลาที่เปิดตัว
  • ดังที่อธิบายไว้ข้างต้น ฟีเจอร์จำนวนมากที่ทุกวันนี้เรามองว่าเป็นเรื่องปกติของการออกแบบระบบ มีอยู่ใน NT มาตั้งแต่แรก ขณะที่ระบบ Unix อื่นแทบทั้งหมดต้องค่อย ๆ เพิ่มความสามารถเหล่านั้นเข้ามาเมื่อเวลาผ่านไป
  • ผลก็คือ ฟีเจอร์เหล่านี้ไม่ได้ผสานเข้ากับปรัชญา Unix ได้อย่างราบรื่นเสมอไป
  • อย่างไรก็ตาม ทุกวันนี้ยังไม่ชัดเจนนักว่า NT "ก้าวหน้ากว่า" Linux หรือ FreeBSD อย่างแท้จริงหรือไม่
    • NT มีหลักการออกแบบที่แข็งแรงกว่าและมีฟีเจอร์มากกว่าระบบปฏิบัติการร่วมยุคตั้งแต่แรกเริ่ม แต่ในปัจจุบันความแตกต่างกลับเลือนราง
    • กล่าวคือ NT มีพัฒนาการขึ้น แต่ไม่ได้ก้าวหน้ากว่า Unix สมัยใหม่อย่างมีนัยสำคัญนัก
  • แม้ NT จะมีหลักการออกแบบที่แข็งแรงทั้งหมดนี้อยู่ แต่ก็น่าเสียดายที่การบวมพองของ UI ทำให้การออกแบบเหล่านี้ไม่สามารถเปล่งประกายได้
    • แม้บนเครื่องที่แรงมาก ความช้าของ OS ก็อาจทำให้ดูแล้วทรมาน และอาจถึงขั้นนำไปสู่จุดจบของ OS นี้ได้

สรุปโดย GN⁺

  • บทความนี้เปรียบเทียบความแตกต่างด้านการออกแบบระหว่าง NT กับ Unix เพื่ออธิบายว่าการออกแบบยุคแรกของ NT มีความล้ำหน้าเพียงใด
  • NT ถูกออกแบบมาตั้งแต่ต้นโดยมีเป้าหมายด้านการพกพาข้ามแพลตฟอร์ม การรองรับมัลติโปรเซสซิง และความเข้ากันได้ ซึ่งเป็นความต่างสำคัญจาก Unix
  • เคอร์เนลเชิงวัตถุ สถาปัตยกรรมหน่วยความจำแบบรวม และอินเทอร์เฟซ I/O แบบอะซิงโครนัสของ NT ล้วนมอบความสามารถที่ก้าวหน้ากว่า Unix
  • อย่างไรก็ตาม ในปัจจุบันความแตกต่างระหว่างระบบ NT และ Unix ไม่ได้มากนัก และความเทอะทะของ UI ใน NT ก็ทำให้ประสิทธิภาพลดลง

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

 
GN⁺ 2024-09-10
ความเห็นจาก Hacker News
  • เคอร์เนล NT นั้นยอดเยี่ยม แต่เป็นการออกแบบที่เก่าแล้ว

    • Windows OS มีองค์ประกอบแบบเก่าจำนวนมากซ้อนอยู่บนเคอร์เนล NT จนก่อให้เกิดปัญหา
    • Microsoft ควรพิจารณาการออกแบบ OS ใหม่ที่อิงกับ NT โดยหลุดพ้นจากกรอบแนวคิด Win32 และ MS-DOS
  • ความแตกต่างที่ใหญ่ที่สุดระหว่าง NT กับ Unix คือแนวทางการเข้าถึงไดรเวอร์

    • NT ถูกออกแบบมาเพื่อแก้ปัญหาไดรเวอร์ของ Windows 3.x/95/98
    • Unix มองว่าไดรเวอร์เป็นองค์ประกอบที่ต้องมีความน่าเชื่อถือสูง และเขียนโดยนักพัฒนาเคอร์เนล
  • ใน WinNT ยุคใหม่ Direct3D เป็นส่วนที่จำเป็นของเคอร์เนล

    • D3D11 ใช้งานได้แม้ไม่มี GPU และมีฟังก์ชันทดแทนแบบซอฟต์แวร์ชื่อ WARP
    • Linux ยังขาดฟังก์ชันที่คล้ายกัน
  • เคอร์เนล NT รันเธรด ไม่ใช่โปรเซส

    • เธรดสามารถสร้างได้ภายในไม่กี่มิลลิวินาที ขณะที่โปรเซสทำงานแบบมีภาระสูงกว่า
    • ประวัติของ NT มีรากฐานมาจากหลักการพื้นฐานของ VMS
  • ในช่วงแรก WindowsNT เป็นระบบที่ออกแบบมาดีกว่า Linux อย่างมาก

    • NT สามารถรัน Win32, OS/2 และ POSIX ได้
    • POSIX ถูกเพิ่มเข้ามาเพื่อรองรับสัญญาซอฟต์แวร์ขนาดใหญ่ของรัฐบาลสหรัฐฯ แต่ภายหลังก็หมดความสนใจ
  • NT ในฐานะระบบที่สาม สามารถหลีกเลี่ยง second-system syndrome ได้

    • OS/2 แก้ปัญหาที่ผิดประเด็นในเชิงเทคนิค และล้มเหลวในเชิงองค์กรด้วย
    • NT ไม่ได้ถูกใช้อย่างแพร่หลายจนกระทั่ง Windows XP
  • จากมุมมองของนักพัฒนา มีความแตกต่างระหว่าง Windows กับ Linux

    • Windows เหนือกว่าในด้าน command line และวิธีการ globbing
    • การใช้ wchar_t ใน Win32 เป็นปัญหา
  • เคอร์เนล NT มีความงดงาม แต่ไม่ใช่โอเพนซอร์ส

    • Windows ที่มี user space และ desktop environment แบบอื่นจะเป็นสิ่งที่น่าสนใจ
  • มีการผสานแนวคิดแบบเดียวกับ FUSE ของ Linux

    • แนวทางจัดการระบบไฟล์ของ Win NT ทำให้งานเกี่ยวกับไฟล์จำนวนมากช้ามาก
    • Microsoft ละทิ้ง WSL1 และใช้คอนเทนเนอร์อย่าง SQLLite หรือไฟล์ ZIP