20 điểm bởi GN⁺ 2024-09-10 | 1 bình luận | Chia sẻ qua WhatsApp
  • NT thường được đánh giá là một hệ điều hành "rất tiên tiến", nhưng trước đây không rõ lý do vì sao
    • Cuối năm 2023, sau khi đọc ấn bản đầu tiên của 'Inside Windows NT', tác giả quyết định so sánh NT với Unix
    • Bài viết này so sánh thiết kế của NT (tháng 7 năm 1993) với các hệ thống Unix cùng thời (4.4BSD, Linux 1.0)
    • Vì là một chuyên gia Unix nhưng không hiểu rõ NT, tác giả tập trung mô tả chủ yếu các điểm khác biệt của NT
    • Bài viết đặt ra câu hỏi NT tốt hơn Unix ở điểm nào, và liệu điều đó có còn đúng đến ngày nay hay không

Sứ mệnh

  • Lịch sử của Unix lâu đời hơn NT rất nhiều
    • Việc phát triển Unix bắt đầu vào năm 1969, và mục tiêu chính là trở thành một nền tảng thuận tiện cho lập trình viên
    • Unix lấy cảm hứng từ Multics, nhưng vượt qua Multics nhờ tập trung vào sự đơn giản
    • Tính di động và đa nhiệm không phải là mục tiêu ban đầu trong thiết kế Unix: các tính năng này được bổ sung vài năm sau đó trong nhiều "nhánh fork" và các lần tái phát minh của Unix
  • Lịch sử của Microsoft
    • Bản phát hành đầu tiên của MS-DOS ra mắt vào tháng 8 năm 1981, và bản phát hành đầu tiên của "Windows di sản" (các phiên bản dựa trên DOS) ra mắt vào tháng 11 năm 1985
    • MS-DOS thành công rộng rãi, nhưng Windows chỉ thực sự trở nên quan trọng từ Windows 3.0 vào tháng 5 năm 1990
    • Windows NT được hình thành vào năm 1989 và xuất hiện trước thế giới với bản phát hành NT 3.1 vào tháng 7 năm 1993
  • Lợi thế của Microsoft
    • Thiết kế của NT bắt đầu muộn hơn Unix 20 năm, điều này mang lại lợi thế cho Microsoft
    • Microsoft đã có sẵn một lượng người dùng lớn nhờ MS-DOS và Windows di sản
    • Nhóm Microsoft thiết kế NT có được hiểu biết từ các quá trình phát triển này, kinh nghiệm phát triển các hệ điều hành khác và khả năng tiếp cận công nghệ hiện đại, nên có thể "nhắm tới mặt trăng" khi tạo ra NT

Kernel

  • Ngoại trừ một vài trường hợp như Minix hay GNU Hurd, Unix được triển khai dưới dạng monolithic kernel và cung cấp một tập hợp system call để tương tác với các chức năng mà hệ điều hành cung cấp
  • Ngược lại, NT là một dạng trung gian giữa monolithic kernel và microkernel: thành phần đặc quyền executive tự biểu lộ như một tập hợp các thành phần mô-đun với các subsystems ở không gian người dùng
  • Các subsystems ở không gian người dùng là các tiến trình đặc biệt chuyển đổi API mà ứng dụng sử dụng (POSIX, OS/2, v.v.) thành các system call của executive
  • Một trong những phần quan trọng của NT executive là HAL, cung cấp các nguyên hàm trừu tượng để truy cập phần cứng của máy và đóng vai trò làm nền tảng cho phần còn lại của kernel
    • Lớp này là chìa khóa giúp NT có thể chạy trên nhiều kiến trúc khác nhau, bao gồm i386, Alpha và PowerPC
    • Unix vào thời điểm đó bị gắn chặt với các kiến trúc cụ thể: khái niệm Unix thì có thể di động, nhưng phần triển khai thì không
    • SunOS ban đầu chỉ hỗ trợ Motorola 68000, 386BSD là bản port BSD đầu tiên sang kiến trúc Intel, còn IRIX là một biến thể Unix dành cho các workstation dựa trên MIPS của Silicon Graphics
  • Một phần quan trọng khác của NT executive là hỗ trợ cho hệ thống multiprocessing và preemptive kernel
    • Kernel có nhiều mức ngắt khác nhau để quyết định điều gì có thể ngắt điều gì khác, giống SPL trong thuật ngữ BSD, nhưng quan trọng hơn là một kernel thread có thể bị một kernel thread khác preempt
    • Đây là điều mà ngày nay mọi hệ thống Unix hiệu năng cao đều làm, nhưng không phải cách mà nhiều hệ Unix ban đầu được xây dựng
    • Các hệ thống đó khởi đầu với kernel không hỗ trợ preemption hoặc multiprocessing, sau đó thêm hỗ trợ multiprocessing ở không gian người dùng, rồi mới thêm kernel preemption
    • Bước cuối cùng là bước khó nhất, và câu chuyện FreeBSD 5.0 cho thấy rõ những khó khăn đó
    • Vì vậy, việc NT ngay từ đầu đã xuất phát từ một nền tảng đúng đắn là điều đáng chú ý

Đối tượng

  • NT là một kernel hướng đối tượng
    • Có thể cho rằng Unix cũng vậy: tiến trình được định nghĩa bằng struct, và việc triển khai file system xử lý vnode ("nút ảo", không nên nhầm với inode)
    • Tuy nhiên, điều này không hoàn toàn giống với cách NT hoạt động: NT buộc tất cả các đối tượng khác nhau đó phải có một biểu diễn chung trong toàn hệ thống
  • Người ta có thể nghi ngờ liệu có thể cung cấp một phép trừu tượng có ý nghĩa cho những thứ không đồng nhất như process và file handle hay không
  • Trên thực tế thì điều đó là không thể hoàn toàn, nhưng NT buộc tất cả chúng phải kế thừa từ một kiểu đối tượng chung, và đáng ngạc nhiên là cách này có một số đặc tính tốt
  • Kiểm soát truy cập tập trung
    • Các đối tượng chỉ được tạo bởi object manager, nên có một điểm duy nhất để đặt mã thực thi chính sách
    • Những ngữ nghĩa như kiểm tra quyền hạn chỉ cần được định nghĩa ở một nơi và có thể được áp dụng đồng nhất cho toàn hệ thống, đây là một ưu điểm mạnh
    • NetBSD cũng đi đến kết luận rằng đây là một ý tưởng hay, nhưng phải đến năm 2001 mới có framework Kernel Authorization (kauth)
  • ID chung
    • Các đối tượng có ID và tất cả đều được biểu diễn trong một cây duy nhất
    • Điều này có nghĩa là tồn tại một namespace duy nhất cho mọi đối tượng, bất kể đó là process, file handle hay pipe
    • Các đối tượng trong cây có thể được định địa chỉ bằng tên (đường dẫn), và các phần khác nhau của cây có thể do các subsystem khác nhau sở hữu
    • Ví dụ, một phần của cây có thể biểu diễn một file system đã được mount, vì vậy khi duyệt nút gốc của cây con đó, file system sẽ tự giải quyết phần còn lại của đường dẫn
    • Điều này tương tự lớp VFS trong các hệ thống Unix, nhưng VFS chỉ xử lý file system, còn cây đối tượng xử lý mọi đối tượng kernel đơn lẻ
    • Unix đã cố gắng nhét các kiểu đối tượng không phải file vào file system thông qua /proc/, /sys/, v.v., nhưng điều đó mang cảm giác như giải pháp chắp vá về sau so với những gì NT cung cấp
  • Xử lý sự kiện hợp nhất
    • Mọi kiểu đối tượng đều có trạng thái signaled, và ý nghĩa của nó khác nhau tùy theo từng kiểu đối tượng
    • Ví dụ, đối tượng process chuyển sang trạng thái signaled khi process kết thúc, còn đối tượng file handle chuyển sang trạng thái signaled khi một yêu cầu I/O hoàn tất
    • Nhờ đó, một system call kiểu wait duy nhất có thể chờ một nhóm đối tượng thay đổi trạng thái, khiến việc viết mã hướng sự kiện ở không gian người dùng (mã async) trở nên rất dễ dàng
    • Trong các hệ thống Unix, việc đồng thời chờ I/O và việc hoàn tất process là một điều rất phiền toái
  • Đối tượng là thành phần đặc thù của NT và không khái quát tốt cho mọi API mà NT muốn hỗ trợ
    • Ví dụ như subsystem POSIX: POSIX không có khái niệm đối tượng như NT, nhưng NT vẫn phải cung cấp một mức độ tương thích nào đó cho các ứng dụng POSIX
    • Vì lý do này, trong khi subsystem POSIX cấp phát các đối tượng trong executive, nó vẫn phải tự duy trì sổ sách nội bộ để biểu diễn các thực thể POSIX tương ứng và ngay lập tức thực hiện chuyển đổi logic giữa hai thực thể
    • Ngược lại, subsystem Win32 chuyển thẳng các đối tượng cho client mà không cần bộ trung gian

Tiến trình

  • Tiến trình là một đối tượng chung của cả NT và Unix, nhưng không hoàn toàn giống nhau
    • Trong Unix, tiến trình được biểu diễn dưới dạng cây, mỗi tiến trình có một tiến trình cha và có thể có 0 hoặc nhiều tiến trình con
    • Tuy nhiên, trong NT không có mối quan hệ như vậy: tiến trình có thể "kế thừa" tài nguyên từ trình tạo ra nó, nhưng sau khi được tạo thì là một thực thể độc lập
  • Vào thời điểm NT được thiết kế, luồng vẫn chưa phổ biến:
    • Mach là kernel kiểu Unix đầu tiên tích hợp luồng vào năm 1985
    • Điều này có nghĩa là các Unix khác phải tiếp nhận khái niệm này về sau và điều chỉnh nó cho phù hợp với thiết kế sẵn có
    • Linux đã chọn biểu diễn luồng như các tiến trình, mỗi tiến trình có PID riêng, trong bản phát hành 2.0 vào tháng 6 năm 1996, còn NetBSD phải đến bản phát hành 2.0 năm 2004 mới có luồng được biểu diễn như một thực thể tách biệt khỏi tiến trình
    • Không giống Unix, NT đã chọn hỗ trợ luồng ngay từ đầu vì biết rằng chúng là thiết yếu cho tính toán hiệu năng cao trên các máy SMP
  • NT không có signal theo nghĩa Unix truyền thống
    • Thay vào đó là alerts, có thể tồn tại ở chế độ kernel và chế độ người dùng
    • Cảnh báo chế độ người dùng phải được chờ giống như các đối tượng khác, còn cảnh báo chế độ kernel thì không hiển thị với tiến trình
    • Hệ con POSIX dùng cảnh báo chế độ kernel để mô phỏng signal
    • Signal thường bị gọi là một “mụn cóc” trong Unix vì cách nó làm gián đoạn việc thực thi tiến trình: xử lý signal đúng cách là một nỗ lực thực sự khó khăn, nên giải pháp thay thế của NT có vẻ thanh nhã hơn
  • Một phát triển thú vị gần đây trong NT là việc đưa vào picoprocesses
    • Trước khi tính năng này được bổ sung, tiến trình trong NT khá nặng: tiến trình mới khi khởi động sẽ nhận một bộ thư viện runtime của NT được ánh xạ vào không gian địa chỉ
    • Trong picoprocess, tiến trình chỉ có liên hệ tối thiểu với kiến trúc Windows, và điều này được dùng để triển khai các tiến trình tương thích Linux trong WSL 1
    • Ở một số khía cạnh, picoprocess gần với tiến trình Unix hơn tiến trình Windows gốc, nhưng do chuyển sang WSL 2 nên dù đã tồn tại từ tháng 8 năm 2016, nó không còn được dùng nhiều nữa
  • Dù Windows thường bị chỉ trích về các vấn đề bảo mật, NT ngay từ đầu đã có một thiết kế bảo mật tiên tiến so với các tiêu chuẩn Internet đời đầu, ở chỗ hệ thống mặc định hoạt động như một hệ thống dựa trên capability
    • Tiến trình người dùng đầu tiên khởi chạy sau khi đăng nhập nhận một access token từ kernel, đại diện cho các quyền của phiên người dùng, và tiến trình cùng các tiến trình con phải đưa token này cho kernel để xác nhận quyền hạn
    • Điều này khác với Unix, nơi tiến trình chỉ có một định danh và kernel phải theo dõi trong bảng tiến trình xem mỗi tiến trình được phép làm gì

Tương thích

  • Mục tiêu chính của NT là tương thích với các ứng dụng được viết cho Windows cũ, DOS, OS/2 và POSIX
    • Một lý do cho điều này là về mặt kỹ thuật, vì nó buộc hệ thống phải có một thiết kế thanh nhã
    • Lý do khác là chính trị, vì NT được đồng phát triển với IBM, và dù cuối cùng NT trở thành Windows thì nó vẫn bắt buộc phải hỗ trợ ứng dụng OS/2
  • Nhu cầu tương thích này khiến thiết kế của NT khác biệt đáng kể so với Unix
    • Trong Unix, ứng dụng không gian người dùng giao tiếp trực tiếp với kernel thông qua giao diện system call, và đó chính là giao diện Unix
    • Thư viện C cung cấp lớp keo để gọi kernel, và ứng dụng không trực tiếp thực thi system call, nhưng đó chỉ là một chi tiết nhỏ
  • Trong NT, ứng dụng không giao tiếp trực tiếp với executive (kernel)
    • Thay vào đó, mỗi ứng dụng giao tiếp với một hệ con được bảo vệ cụ thể, và các hệ con này triển khai API của nhiều hệ điều hành khác nhau mà NT muốn tương thích
    • Các hệ con này được triển khai như các server không gian người dùng (không nằm trong “microkernel” của NT)
    • Hỗ trợ cho ứng dụng Windows được cung cấp bởi server Win32, và đây là server đặc biệt vì là server duy nhất người dùng có thể nhìn thấy trực tiếp: nó điều khiển các chương trình console và terminal DOS, đồng thời có một số đặc quyền vì lý do hiệu năng
  • So với Unix truyền thống, thiết kế của NT rất khác vì BSD và Linux có kernel nguyên khối
    • Các kernel này công khai giao diện system call mà ứng dụng không gian người dùng sử dụng để tương tác trực tiếp với hệ thống
    • Tuy nhiên, BSD từ lâu đã hỗ trợ thực thi binary thay thế ngay trong kernel nguyên khối: nó hoạt động bằng cách công khai các bảng system call khác nhau cho không gian người dùng tùy theo binary đang chạy, rồi chuyển đổi các system call “ngoại lai” đó thành thứ mà kernel hiểu
    • Linux cũng cung cấp hỗ trợ hạn chế cho việc này thông qua personalities
  • Dù cách tiếp cận của BSD rất khác với cách NT hỗ trợ các hệ thống khác, WSL 1 lại rất giống như vậy và không phải là một hệ con theo đúng thuật ngữ ban đầu
    • Trong WSL 1, kernel NT đánh dấu tiến trình Linux là picoprocess, rồi từ đó công khai một giao diện system call khác
    • Bên trong kernel NT, các system call liên quan đến Linux đó được chuyển thành các thao tác NT, được cung cấp trong cùng một kernel tương tự như khả năng tương thích Linux của BSD
    • Vấn đề duy nhất là vì NT không phải Unix nên việc “mô phỏng” Linux rất phức tạp và chậm hơn nhiều so với những gì BSD có thể cung cấp
    • Thật đáng tiếc khi WSL 2 đã đánh mất bản chất của thiết kế này và chuyển sang một thiết kế VM hoàn chỉnh
  • Chi tiết thú vị trong thiết kế NT
    • Mục tiêu của thiết kế NT là cho phép chuyển hướng I/O liền mạch giữa các hệ con trong một shell duy nhất
    • Các hệ con được công khai cho ứng dụng thông qua port, đây là các đối tượng của NT và tương tự cách Mach cho tiến trình và server giao tiếp với nhau

Bộ nhớ ảo

  • Cũng như Unix, NT dựa vào Memory Management Unit (MMU) có phân trang để cung cấp cơ chế bảo vệ giữa các tiến trình và cung cấp bộ nhớ ảo
    • Phân trang cho tiến trình không gian người dùng là cơ chế thông thường để cung cấp một không gian địa chỉ lớn hơn lượng bộ nhớ vật lý của máy
    • Tuy nhiên, một điểm giúp NT đi trước các hệ Unix cùng thời là chính kernel cũng có thể bị phân trang ra đĩa
    • Nếu toàn bộ kernel đều có thể phân trang thì có thể rơi vào tình huống cần mã của một trình điều khiển hệ thống tệp đã bị phân trang ra ngoài để xử lý một kernel page fault, nhưng phần lớn kernel vẫn có thể phân trang
    • Ngày nay điều này không còn quá thú vị vì kernel nhỏ so với lượng bộ nhớ thường được lắp trong máy, nhưng trước đây khi từng byte đều quý giá thì khác biệt này rất lớn
  • Ngày nay chúng ta xem cách bộ nhớ ảo và phân trang hoạt động là điều hiển nhiên, nhưng vào thời NT được thiết kế, đây là một lĩnh vực nghiên cứu lớn
    • Các triển khai Unix trước đó có bộ đệm bộ nhớ riêng cho hệ thống tệp và bộ nhớ ảo, và phải đến năm 1987 SunOS mới triển khai một kiến trúc bộ nhớ ảo hợp nhất để giảm chi phí phụ trội của thiết kế trước đó
    • Trong khi đó NT đã bắt đầu với một kiến trúc bộ nhớ hợp nhất ngay từ đầu
    • Có thể nói điều này dễ thực hiện hơn vì đã có những hiểu biết về các điểm kém hiệu quả trong Unix và đã có thể nhìn thấy giải pháp mà SunOS triển khai trước khi việc thiết kế NT bắt đầu
    • Tuy nhiên, cần lưu ý rằng điều này khiến NT “tiên tiến” hơn nhiều hệ điều hành khác vào thời đó, và các hệ thống khác phải đến năm 2002 với việc triển khai Unified Buffer Cache (UBC) của NetBSD 1.6 mới bắt kịp
  • Một khác biệt thú vị giữa NT và Unix là cách chúng quản lý và biểu diễn bộ nhớ chia sẻ
    • Trong NT, các vùng bộ nhớ chia sẻ là đối tượng, nên chúng trải qua cùng một cơ chế kiểm tra hiệu lực truy cập như mọi đối tượng khác
    • Chúng cũng là một phần của cây đối tượng duy nhất, nên có thể được định địa chỉ theo cùng cách như mọi đối tượng khác
    • Trong Unix, tính năng này được gắn thêm vào: các đối tượng bộ nhớ chia sẻ có namespace riêng, API riêng với các thực thể khác, nên các quyền hạn thông thường không được áp dụng

Hệ thống con I/O

  • Các phiên bản Unix ban đầu chỉ hỗ trợ một hệ thống tệp duy nhất
    • Ví dụ, BSD phải đến 4.3BSD vào tháng 4 năm 1990 mới có được lớp trừu tượng Virtual File System (VFS) để hỗ trợ nhiều hơn UFS
    • Trong khi đó, NT được thiết kế ngay từ đầu để cho phép nhiều hệ thống tệp
  • Để hỗ trợ nhiều hệ thống tệp, kernel phải phơi bày namespace đó theo cách nào đó
    • Unix kết hợp các hệ thống tệp trong một hệ thống phân cấp tệp duy nhất thông qua mount point: lớp VFS cung cấp cơ chế nhận diện node tương ứng với gốc của hệ thống tệp và chuyển hướng yêu cầu tới driver hệ thống tệp đó khi duyệt đường dẫn
    • NT có thiết kế tương tự dù trong giao diện người dùng tiêu chuẩn, các hệ thống tệp xuất hiện như các ổ đĩa tách biệt: về mặt nội bộ, executive biểu diễn hệ thống tệp thành các đối tượng trong cây đối tượng và mỗi đối tượng chịu trách nhiệm phân tích phần còn lại của đường dẫn
    • Các đối tượng hệ thống tệp đó sau đó được ánh xạ lại thành ổ đĩa DOS để có thể truy cập từ không gian người dùng
    • Các ổ đĩa DOS cũng là các đối tượng nằm dưới một cây con riêng biệt, nơi chuyển hướng I/O tới hệ thống tệp mà chúng tham chiếu
  • NT cuối cùng đã được phát hành cùng với NTFS
    • Dù NTFS thường bị chê vì hiệu năng kém (một nhận định sai), vào thời điểm đó đây thực sự là một hệ thống tệp rất tiên tiến
    • Hệ thống con I/O của NT, kết hợp với NTFS, cung cấp địa chỉ hóa 64-bit, journaling và thậm chí cả tên tệp Unicode
    • Linux mãi tới cuối thập niên 1990 mới hỗ trợ tệp 64-bit, và phải tới khi ext3 ra mắt năm 2001 mới có journaling
    • Soft updates, một cơ chế thay thế cho khả năng chịu lỗi, phải tới năm 1998 mới xuất hiện trong FreeBSD
    • Unix biểu diễn tên tệp dưới dạng mảng byte kết thúc bằng null thay vì Unicode
  • Các tính năng khác có mặt khi NT ra mắt gồm có disk striping và mirroring (ngày nay được gọi là RAID) cùng với hot-plug thiết bị
    • Những tính năng này không phải hoàn toàn mới vì SunOS đã hỗ trợ RAID từ đầu thập niên 1990, nhưng điều đáng chú ý là tất cả đều đã được tính đến như một phần của thiết kế ban đầu
    • Ở cấp độ cao hơn, điều khiến hệ thống con I/O của NT tiên tiến hơn Unix rất nhiều là giao diện của nó về bản chất là bất đồng bộ, và đã như vậy ngay từ đầu
    • Để dễ hình dung, FreeBSD phải đến FreeBSD 3.0 năm 1998 mới có hỗ trợ cho aio(7), còn Linux phải đến Linux 2.5 năm 2002 mới có
    • Dù hỗ trợ bất đồng bộ I/O đã tồn tại trên các hệ thống Unix hơn 20 năm, nó vẫn chưa được dùng rộng rãi: hầu như không ai biết các API này, đa số ứng dụng không dùng chúng, và hiệu năng cũng không tốt
    • io_uring của Linux là một bổ sung tương đối mới nhằm cải thiện bất đồng bộ I/O, nhưng đã trở thành nguyên nhân chính của các lỗ hổng bảo mật và cũng không được sử dụng rộng rãi

Mạng

  • Ngày nay Internet có mặt khắp nơi, nhưng khi NT được thiết kế thì chưa phải vậy
    • Nhìn vào hệ sinh thái Microsoft, DOS 3.1 (1987) có bao gồm nền tảng để chia sẻ tệp trên hệ thống tệp FAT, nhưng bản thân “OS” không cung cấp tính năng mạng: một sản phẩm riêng mang tên Microsoft Networks (MS-NET) đảm nhiệm việc đó
    • Windows 3.0 (1990) có hỗ trợ NetBIOS, cho phép chia sẻ máy in và tệp cơ bản trong mạng cục bộ, nhưng không hề có hỗ trợ TCP/IP
  • Trong khi đó, Unix gần như chính là Internet: tất cả các giao thức Internet nền tảng đều được viết trên Unix và cùng với Unix
    • Trong quá trình thiết kế NT, việc cân nhắc hỗ trợ mạng tốt là rất quan trọng, và thực tế NT đã được phát hành kèm khả năng mạng
    • Kết quả là NT hỗ trợ cả các giao thức Internet lẫn các giao thức LAN truyền thống được dùng trong môi trường Microsoft trước đó, điều này giúp NT vượt lên trước Unix trong môi trường doanh nghiệp
  • Ví dụ có thể kể đến network domain của NT
    • Trên Unix, quản trị viên mạng thường phải đồng bộ tài khoản người dùng giữa các máy theo cách thủ công
    • Các hệ thống như SunOS có thể dùng giao thức thư mục X.500 (1988) và Kerberos (thập niên 1980) cho xác thực người dùng, nhưng các công nghệ này không hề đơn giản
    • Ngược lại, NT ngay từ đầu đã cung cấp domain tích hợp sẵn chức năng thư mục và xác thực, dường như đã “chiến thắng” trong mạng công ty vì dễ thiết lập hơn nhiều và được tích hợp sẵn trong hệ thống
  • Mục tiêu của việc đồng bộ tài khoản người dùng là chia sẻ tài nguyên giữa các máy, chủ yếu là tệp, và khi làm vậy thì cách biểu diễn quyền hạn là điều quan trọng
    • Trong thời gian dài, Unix chỉ cung cấp một tập quyền đọc/ghi/thực thi đơn giản cho mỗi tệp
    • Trong khi đó, NT ngay từ đầu đã đi kèm ACL nâng cao, điều mà đến nay vẫn là điểm đau của Unix
    • Linux và BSD giờ cũng có ACL, nhưng giao diện giữa các hệ thống không nhất quán và tạo cảm giác như một phần bổ sung xa lạ với thiết kế hệ thống
    • Trong NT, ACL hoạt động ở cấp đối tượng nên được áp dụng nhất quán cho mọi chức năng của kernel
  • Khi nói về chia sẻ tệp, cũng phải nói tới hệ thống tệp mạng
    • Trên Unix, hệ thống tệp thực tế là NFS, còn trên NT là SMB
    • SMB được thừa hưởng từ MS-NET và LAN Manager, và được triển khai trong kernel thông qua một thành phần gọi là redirector
    • Về bản chất, redirector chỉ là một hệ thống tệp “đơn giản” khác, có nhiệm vụ chặn các thao tác tệp và gửi chúng qua mạng, tương tự như NFS trong Unix
  • protobufgRPC có thể đang được dùng rộng rãi đến mức trông như ý tưởng mới, nhưng thực ra chúng dựa trên những ý tưởng cũ
    • Trên Unix, Sun RPC đã được sử dụng từ đầu thập niên 1980, chủ yếu để hỗ trợ NFS
    • Tương tự, NT đi kèm hỗ trợ RPC tích hợp, với DSL riêng của nó (được biết đến với tên MIDL để chỉ định định nghĩa giao diện và sinh mã cho các thủ tục từ xa) và các tính năng riêng để triển khai client và server RPC
  • Các hệ thống Unix không quá tập trung vào hỗ trợ driver tùy ý: chúng thường gắn chặt với một máy và nhà cung cấp cụ thể
    • Trong khi đó, NT muốn trở thành OS cho “mọi” loại máy, lại được bán bởi một công ty phần mềm, nên hỗ trợ cho các driver do bên khác viết là rất quan trọng
    • Vì vậy NT đi kèm Network Driver Interface Specification (NDIS), một lớp trừu tượng giúp hỗ trợ driver card mạng dễ dàng hơn
    • Cho đến ngày nay, driver do nhà sản xuất cung cấp vẫn không quá phổ biến trên Linux, và điều này đã tạo ra những công cụ thú vị như ndiswrapper, từng rất phổ biến vào đầu những năm 2000 vì cho phép tái sử dụng driver Windows cho card WiFi trên Linux
  • Cuối cùng, một khác biệt khác giữa NT và Unix nằm ở cách triển khai named pipe
    • Named pipe là một thành phần cục bộ trong Unix: nó cung cấp cơ chế để hai tiến trình trên cùng một máy giao tiếp với nhau bằng một tên tệp tồn tại bền vững trên đĩa
    • NT cũng có chức năng tương tự, nhưng named pipe có thể hoạt động qua mạng
    • Nếu đặt named pipe trên một hệ thống tệp chia sẻ, hai ứng dụng trên các máy tính khác nhau có thể giao tiếp với nhau mà không cần bận tâm đến các chi tiết mạng

User-Space

  • Cấu hình:
    • NT tập trung hóa cấu hình hệ thống và ứng dụng trong một cơ sở dữ liệu gọi là registry, rời xa CONFIG.SYS, AUTOEXEC.BAT đã cũ và vô số tệp INI được dùng trong Windows đời cũ
    • Điều này khiến một số người rất khó chịu, nhưng cuối cùng giao diện cấu hình hợp nhất lại có lợi cho tất cả mọi người: việc viết ứng dụng trở nên dễ hơn vì chỉ có một nền tảng cần hỗ trợ, và người dùng cũng có thể tinh chỉnh hệ thống dễ hơn vì chỉ có một nơi để kiểm tra
    • Trong khi đó, Unix vẫn gặp khó khăn với hàng chục DSL và vị trí tệp thiếu nhất quán
    • Mỗi chương trình hỗ trợ tệp cấu hình đều có cú pháp riêng, và việc biết chương trình đọc ở đâu là điều khó khăn cũng như không phải lúc nào cũng được tài liệu hóa đầy đủ
    • Hệ sinh thái Linux đã thúc đẩy một cách tiếp cận giống NT thông qua XDG và dconf (trước đây là GConf), nhưng trong khi các thành phần desktop dùng gần như độc quyền các công nghệ này thì các thành phần cốt lõi của hệ thống lại không áp dụng, để lại một mớ hỗn độn thiếu nhất quán
  • Quốc tế hóa:
    • Microsoft, với tư cách là một công ty lớn đã phát hành Windows 3.x trên toàn thế giới, hiểu rằng bản địa hóa là điều quan trọng và đã xây dựng NT để hỗ trợ những khả năng này ngay từ đầu
    • Hãy đối chiếu điều đó với Unix, nơi hỗ trợ UTF mãi đến cuối thập niên 1990 mới bắt đầu xuất hiện và việc hỗ trợ các ngôn ngữ khác được thực hiện thông qua tiện ích bổ sung gettext mang tính tùy chọn
  • Ngôn ngữ C:
    • Một điều mà các hệ thống Unix như FreeBSD và NetBSD đã mơ ước từ lâu là tự tạo ra phương ngữ C riêng để hiện thực kernel theo cách an toàn hơn
    • Điều này đã không đi đến đâu, ngoại trừ Linux vốn dựa vào các phần mở rộng chỉ dành cho GCC
    • Ngược lại, Microsoft có đặc quyền sở hữu trình biên dịch C của riêng mình, nên đã làm điều đó trong NT được viết bằng Microsoft C
    • Ví dụ, NT dựa vào Structured Exception Handling (SEH), một tính năng bổ sung các mệnh đề try/except để xử lý các ngoại lệ phần mềm và phần cứng
    • Tôi sẽ không nói đây là một lợi thế lớn, nhưng nó thực sự là một khác biệt

Kết luận

  • NT là một công nghệ đột phá vào thời điểm nó ra mắt
  • Như đã mô tả ở trên, nhiều tính năng mà ngày nay chúng ta coi là hiển nhiên trong thiết kế hệ thống đã có mặt trong NT ngay từ đầu, trong khi gần như mọi hệ thống Unix khác đều phải dần dần bổ sung những tính năng đó theo thời gian
  • Kết quả là, các tính năng này không phải lúc nào cũng được tích hợp trơn tru với triết lý Unix
  • Tuy nhiên, ngày nay vẫn chưa rõ liệu NT có thực sự "tiên tiến hơn" Linux hay FreeBSD hay không
    • NT có các nguyên tắc thiết kế vững chắc hơn và nhiều tính năng hơn các hệ điều hành cùng thời ngay từ đầu, nhưng ngày nay sự khác biệt đã trở nên mơ hồ
    • Nói cách khác, NT đã tiên tiến, nhưng không còn tiên tiến vượt trội đáng kể so với Unix hiện đại
  • Dù NT có tất cả những nguyên tắc thiết kế vững chắc này, thật đáng tiếc khi thiết kế đó không thể tỏa sáng vì sự phình to của UI
    • Ngay cả trên những cỗ máy cực mạnh, sự chậm chạp của hệ điều hành vẫn có thể là điều khó chịu khi chứng kiến, và thậm chí có thể dẫn đến sự kết thúc của hệ điều hành này

Tóm tắt của GN⁺

  • Bài viết này so sánh khác biệt trong thiết kế giữa NT và Unix để giải thích thiết kế ban đầu của NT đã tiến bộ đến mức nào
  • NT được thiết kế ngay từ đầu với mục tiêu tính di động, hỗ trợ đa xử lý và khả năng tương thích, đây là những khác biệt chính so với Unix
  • Kernel hướng đối tượng, kiến trúc bộ nhớ hợp nhất và giao diện I/O bất đồng bộ của NT cung cấp các tính năng tiên tiến hơn so với Unix
  • Tuy nhiên, ngày nay khác biệt giữa NT và các hệ thống Unix không còn lớn, và sự phình to của UI trong NT gây ra suy giảm hiệu năng

1 bình luận

 
GN⁺ 2024-09-10
Ý kiến trên Hacker News
  • Nhân NT rất xuất sắc nhưng là một thiết kế cũ

    • Hệ điều hành Windows có nhiều thành phần lỗi thời chồng chất lên trên nhân NT nên phát sinh vấn đề
    • Microsoft nên cân nhắc một thiết kế hệ điều hành mới dựa trên NT, thoát khỏi mô hình Win32 và MS-DOS
  • Khác biệt lớn nhất giữa NT và Unix là cách tiếp cận với driver

    • NT được thiết kế để giải quyết các vấn đề driver của Windows 3.x/95/98
    • Unix xem driver là các thành phần có độ tin cậy cao và do các lập trình viên kernel viết
  • Trong WinNT hiện đại, Direct3D là phần thiết yếu của kernel

    • D3D11 có thể dùng ngay cả khi không có GPU và cung cấp tính năng thay thế bằng phần mềm gọi là WARP
    • Linux thiếu một tính năng tương tự như vậy
  • Nhân NT chạy thread chứ không phải process

    • Thread có thể được tạo trong vài mili giây, còn process hoạt động nặng nề hơn
    • Lịch sử của NT bắt nguồn từ các nguyên tắc nền tảng của VMS
  • WindowsNT ban đầu là một hệ thống được thiết kế tốt hơn Linux rất nhiều

    • NT có thể chạy Win32, OS/2 và POSIX
    • POSIX được bổ sung để phục vụ các hợp đồng phần mềm lớn của chính phủ Mỹ, nhưng về sau mất đi sự quan tâm
  • NT là hệ thống thứ ba nên đã tránh được hội chứng hệ thống thứ hai

    • OS/2 giải quyết sai vấn đề về mặt kỹ thuật và cũng thất bại về mặt tổ chức
    • NT không được sử dụng rộng rãi cho đến tận Windows XP
  • Từ góc nhìn của nhà phát triển, có những khác biệt giữa Windows và Linux

    • Windows tốt hơn ở dòng lệnh và cách globbing
    • Việc Win32 sử dụng wchar_t là một vấn đề
  • Nhân NT có sự tao nhã, nhưng không phải mã nguồn mở

    • Một phiên bản Windows với không gian người dùng và môi trường desktop khác sẽ rất thú vị
  • Đã từng có sự hội tụ như FUSE của Linux

    • Cách tiếp cận hệ thống tệp của Win NT khiến nhiều tác vụ với hệ thống tệp trở nên rất chậm
    • Microsoft đã từ bỏ WSL1 và sử dụng các container như SQLLite hoặc tệp ZIP