13 điểm bởi GN⁺ 2025-10-17 | 2 bình luận | Chia sẻ qua WhatsApp
  • Dự án Rust for Linux đang thúc đẩy các tính năng ngôn ngữ cốt lõi cần thiết cho phát triển kernel, đồng thời đóng góp vào sự phát triển của chính ngôn ngữ Rust
  • Ba nội dung cốt lõi là field projection, khởi tạo tại chỗ (in-place initialization)kiểu Self tùy ý (arbitrary self types)
  • Những tính năng này giúp biểu diễn tự nhiên hơn bằng Rust các cấu trúc đặc thù của kernel như smart pointer, bộ nhớ được ghim (Pin), RCU
  • Nhóm Rust coi trọng sự ổn định trong thiết kế nên tốc độ phát triển chậm, nhưng nhờ có mục tiêu rõ ràng là kernel Linux nên mức độ tập trung phát triển được nâng cao
  • Đây là những thay đổi có sức lan tỏa tới cả hệ sinh thái Rust ngoài kernel, được kỳ vọng sẽ hỗ trợ lớn cho việc xử lý smart pointer và đơn giản hóa mã nguồn

Cải tiến ngôn ngữ Rust và vai trò của kernel Linux

  • Lý do việc phát triển các tính năng mới của Rust diễn ra chậm là vì sự thận trọng nhằm tránh cố định các thiết kế tồi vào ngôn ngữ và vấn đề “căn chỉnh sự chú ý” (alignment in attention)
    • Dự án Rust được vận hành bởi các tình nguyện viên, nên nếu không có ai tập trung vào một tính năng cụ thể thì việc phát triển sẽ bị chậm lại
  • Dự án Rust for Linux là một chủ đề khiến nhiều người hào hứng, vì vậy nó giúp tập trung nỗ lực vào một số tính năng cốt lõi cần cho kernel
  • Đồng lãnh đạo nhóm ngôn ngữ Rust, Tyler Mandry, đã công bố các tính năng ngôn ngữ Rust sắp ra mắt tại Kangrejos 2025 và nhắc rằng dự án kernel Linux đã đóng vai trò chất xúc tác cho sự phát triển của Rust
    • Các tính năng chính: field projection, khởi tạo tại chỗ (in-place), kiểu self tùy ý (arbitrary self types)
    • Việc phát triển kernel đã đưa ra ca sử dụng thực tế và các yêu cầu kỹ thuật rõ ràng, góp phần cụ thể hóa định hướng thiết kế ngôn ngữ Rust
    • Ưu tiên cao nhất là chuẩn hóa các tính năng unstable đã được dùng trong kernel bindings

Field Projection

  • Đây là tính năng trích xuất con trỏ tới một trường cụ thể từ con trỏ tới struct, là nỗ lực tổng quát hóa biểu thức &(r->field) của C trong Rust
  • Trước đây chỉ có thể thực hiện với tham chiếu (&)con trỏ (*mut), còn với smart pointer do người dùng định nghĩa thì bị hạn chế
  • Rust for Linux đang thúc đẩy mở rộng điều này để có thể truy cập trường bằng cùng một cú pháp trên mọi kiểu con trỏ
  • Đặc biệt, khi xử lý kiểu Pin (struct không thể di chuyển), tính năng này được thiết kế để khi field projection sẽ tự động chuyển thành Pin<&mut Field> hoặc &mut Field
  • Nếu được triển khai, tính năng này có thể hỗ trợ an toàn mẫu RCU (Read-Copy-Update) trong Rust, cho phép truy cập dữ liệu hiệu năng cao mà không cần lock
  • Hiện đang được thảo luận trong tracking issue trên GitHub, với mục tiêu ổn định hóa trước Debian 14 (2027)

Arbitrary Self Types

  • Đây là tính năng cho phép định nghĩa method chấp nhận smart pointer
  • Trước đây chỉ hỗ trợ dạng fn method(&self), nhưng giờ có thể hỗ trợ cả dạng như fn method(self: Pin<&mut MyStruct>)
  • Đây là tính năng thiết yếu trong kernel vì sử dụng nhiều wrapper con trỏ như Arc, Pin, Mutex
  • Trong quá trình triển khai đã có vấn đề xung đột với trait Deref, nhưng đang được giải quyết bằng cách đưa vào trait Receiver mới
  • Receiver có vai trò chỉ rõ rằng một con trỏ có thể được dùng như kiểu Self tùy ý
  • Trong phát triển kernel, điều này giúp giữ cho các lời gọi chuỗi con trỏ ngắn gọn hơn
  • Ding đang dùng công cụ Crater để kiểm chứng khả năng tương thích với các package Rust hiện có, và cho biết có khả năng được ổn định hóa trong vòng 1 năm

In-place Initialization

  • Đây là tính năng hỗ trợ ở cấp độ ngôn ngữ cho macro pin_init!() đang được dùng trong kernel
  • Nó cho phép khởi tạo đối tượng trực tiếp trên bộ nhớ mà không di chuyển sau khi tạo, hữu ích cho struct Pin, Future, trait object dyn
  • Hiện có ba đề xuất đang được thảo luận song song
    • Cách dùng từ khóa init: bổ sung cú pháp ở mức tối thiểu và tận dụng trait PinInit hiện có
    • Cách dùng tham chiếu &out: bổ sung tham chiếu chỉ-ghi như con trỏ out của C, hỗ trợ khởi tạo theo từng field
    • Cách tối ưu kiểu C++: với các đối tượng sẽ được chuyển ngay lên heap, tạo trực tiếp trên heap ngay từ đầu
  • Cuối cùng, kế hoạch là thử nghiệm cả PinInit và cách dùng out-reference để kiểm chứng tính khả dụng thực tế
  • Nếu tính năng này được đưa vào, nó được kỳ vọng sẽ đơn giản hóa cấu trúc không chỉ cho kernel mà còn cho toàn bộ mã Rust bất đồng bộ

Rust for Linux tác động tới Rust như thế nào

  • Kernel Linux đang đóng vai trò như một testbed thực tế cho sự phát triển của ngôn ngữ Rust
  • Cả ba tính năng đều bắt nguồn từ các yêu cầu đặc thù của kernel như smart pointer, bộ nhớ được ghim, cấu trúc đồng thời, nhưng
    cuối cùng các lập trình viên Rust nói chung cũng sẽ được hưởng lợi
  • Những thay đổi này được đánh giá là ví dụ cho vòng tuần hoàn tích cực giữa phát triển kernel và phát triển ngôn ngữ

2 bình luận

 
GN⁺ 2025-10-17
Ý kiến Hacker News
  • Tôi đã mất khá nhiều thời gian để đọc và hiểu tài liệu RFC về tính năng lightweight clones của Rust. Lúc đầu tôi thấy tính năng này khá thú vị, nhưng rồi lại một lần nữa cảm nhận rằng Rust là một ngôn ngữ khó học. Với người như tôi, chưa thực sự học bài bản Rust hay C++, nó tạo cảm giác như mọi khái niệm và tính năng của modern C++ được trộn với các yếu tố của Haskell. Dù vậy, nhìn việc mọi người tạo ra rất nhiều thứ hữu ích bằng Rust thì vẫn có cảm giác là có gì đó rất đúng đắn ở đây. Vì thế tôi định sẽ sớm thử nghiêm túc dùng Rust thêm một lần nữa. Liên kết RFC liên quan

    • Theo kinh nghiệm của tôi thì C++ phức tạp hơn Rust rất nhiều. Ví dụ chỉ riêng cách khởi tạo đã có 8 kiểu, kiểu giá trị thì có tới 5 loại như xvalue, quy ước định dạng và đặt tên cũng không nhất quán, rồi còn rule of 5, xử lý ngoại lệ, lúc move assignment lại luôn phải kiểm tra this != other, perfect forwarding, SFINAE, các vấn đề với vật thay thế trait, cùng vô số điểm phức tạp khác. Muốn dùng C++ cho ra hồn thì còn phải học cả các convention xây trên tiêu chuẩn để viết code an toàn và nhanh, mà nhiều cách như xử lý ngoại lệ lại xung đột lẫn nhau hoặc buộc phải chọn những cách làm không lý tưởng

    • Trong cộng đồng Rust, bầu không khí đối với đề xuất lightweight clones đang ngày càng tiêu cực. Lý do là vì nó quá phức tạp. Ngay cả trong tài liệu chính thức của Rust về hướng thiết kế, độ phức tạp cũng là trở ngại lớn nhất. Không phải mọi tính năng được đề xuất cho Rust đều bắt buộc phải đơn giản, nhưng lightweight clone chỉ giúp làm một việc vốn đã làm được trở nên dễ hơn một chút, và nếu mọi người không thể dễ dàng hiểu nó thì đó là vấn đề

    • Rust nhìn từ xa thì có vẻ rất đồ sộ, nhưng khi thật sự code thì lại quen rất nhanh. Ví dụ ban đầu tôi hoàn toàn không hiểu khái niệm lifetime nên chỉ code bằng Rc<>. Sau khi nắm được các kiến thức nền tảng rồi quay lại học lifetime thì thấy dễ hơn nhiều. Thật ra đa số người dùng sẽ chẳng bao giờ phải bận tâm đến các tính năng như lightweight clones

    • So với C thì rất phức tạp, nhưng so với C++ thì đơn giản hơn nhiều. Mức độ gần như là không cần phải lục tài liệu hay sách tham khảo chỉ để hiểu code. Rust ở một vị trí rất vừa phải: "không quá phức tạp đến mức rụng tóc, cũng không quá đơn giản đến mức code trở nên rối rắm". Hơn nữa, mặc định code đã có tính đúng đắn

    • Độ phức tạp của Rust cũng ít dẫn đến việc vô tình dùng sai như trong C++. Và nếu dùng clippy thì nó còn tự động đề xuất chuyển sang code idiomatic hơn, nên ngay cả các tính năng mới như lightweight clones, bạn không cần tự biết trước mà vẫn sẽ được gợi ý. Phần lớn có thể áp dụng dễ dàng chỉ bằng tùy chọn --fix của clippy. Đây là điểm khác biệt mang tính quyết định với C++, nơi các tính năng không dùng đến cứ tích tụ hoặc bị dùng theo cách quá mức phức tạp, khiến độ phức tạp tiếp tục chồng chất như một tác dụng phụ

  • Có người nói dự án Rust for Linux đã giúp ích rất nhiều cho Rust, nên vì tò mò tôi thử tìm các file "*.rs" trong cây mã kernel. Nhìn vào thì thấy dưới thư mục rust có một lớp tương thích API, còn trong cây kernel chỉ có một ít driver proof of concept đơn thuần rewrite lại driver cũ (ngoại trừ driver nvidia còn chưa hoàn chỉnh), và có vẻ gần như chưa có gì được dùng thực tế. Bản rewrite Android binder bằng Rust cũng cho cảm giác chỉ còn tồn tại ở mức gần như treo đó. Ấn tượng tổng thể của tôi là đây chỉ là một dự án thử nghiệm nho nhỏ, và tôi băn khoăn liệu có cần thực hiện kiểu thử nghiệm đồng phát triển ngôn ngữ như vậy ngay trong source tree của phần mềm quan trọng nhất thế giới hay không. Có lẽ làm ở một OS mang tính thử nghiệm hơn như Redox sẽ phù hợp hơn

    • Driver GPU cho Apple silicon được viết bằng Rust, và chính tác giả nói rằng nếu phát triển bằng C thì sẽ khó hơn rất nhiều. Dù chưa được đưa upstream, nhưng ông ấy nói rằng: "khi tạo mới một driver kernel phức tạp thì đủ loại vấn đề như race condition, memory leak, use-after-free rất dễ bùng lên, còn khi viết bằng Rust thì gần như không có các vấn đề đó và nó hoạt động ổn định. Nhờ các tính năng an toàn, tôi có thể tin chắc rằng driver này thread-safe và memory-safe, và bản thân thiết kế cũng tự nhiên đi theo hướng tốt. Tôi nghĩ đó là phép màu của Rust". Liên kết chia sẻ trải nghiệm của tác giả Và về câu hỏi liệu có nên làm kiểu thử nghiệm này trong cây kernel hay không, có nhắc rằng Torvalds không đồng ý với nhận định đó

    • Ý kiến cho rằng "bản rewrite Android binder bằng Rust chỉ còn tồn tại treo đó" là không đúng. Dự án này hiện có kế hoạch thay thế hoàn toàn bản triển khai bằng C. Bài viết liên quan Các driver chính cho phần cứng Apple dòng M cũng được viết bằng Rust, và đó không phải chỉ là rewrite đơn giản hay proof of concept

    • Để tạo được các driver phức tạp thì trước hết cần có một lớp giao diện. Dự án RfL đang làm việc để thêm lớp hạ tầng như vậy vào upstream, và phải xây được nền tảng đó thì mới có thể viết các driver phức tạp. Redhat đang làm nova, asahi đang làm Apple GPU, collabora đang làm cho ARM Mali. Nếu ba driver GPU đó vẫn chưa được coi là driver phức tạp thì tôi cũng không biết thế nào mới gọi là driver phức tạp nữa

    • Về nhận định rằng bản rewrite binder bằng Rust chỉ còn tồn tại treo đó, nhìn vào commit message trong cây của Linus thì có thể thấy mức độ hoàn thiện đã rất cao. Rust binder đã vượt qua toàn bộ các bài test binder của Android Open Source Project, và nhiều ứng dụng cũng như tính năng khác nhau hoạt động bình thường không có vấn đề đáng kể. Trên cuttlefish emulator và Pixel 6 Pro cũng không có vấn đề khi khởi động và chạy ứng dụng. Tính năng hiện tại cũng tương đương binder bản C, chỉ còn thiếu một số chức năng debug và sẽ sớm được bổ sung. Ngoài ra, dự án Rust for Linux ban đầu đúng là xuất phát ngoài cây kernel, nhưng nếu muốn thật sự thử nghiệm tích hợp thực tế thì cuối cùng vẫn phải thử ngay trong tree

    • Mục tiêu của dự án này không phải là một thử nghiệm đồng phát triển ngôn ngữ, mà là dùng Rust cho phát triển kernel Linux. Các nhà phát triển nòng cốt muốn dùng Rust nên họ tự khởi động dự án. Vì đây là phần mềm cực kỳ quan trọng nên mọi thứ đang được tiến hành thận trọng, và mất thời gian để xây nền tảng cơ bản. Việc Rust được hưởng lợi thêm từ dự án này chỉ là hiệu ứng phụ

  • Trong bài có đoạn <i>liên quan đến field projection, đã có quyết định rằng mọi field của struct giờ sẽ được pin theo cấu trúc để luôn cho ra các kiểu như Pin<&mut Field></i>, và tôi nhận ra trước đây mình đã bỏ lỡ phần này. Đây là vấn đề phức tạp về mặt kỹ thuật, nhưng tôi rất mừng vì quyết định này đã tháo gỡ được một nút thắt từng cản trở nhiều cuộc thảo luận

  • Mọi người đang thảo luận về <i>thiết kế cuối cùng lấy cảm hứng từ C++, một kỹ thuật tối ưu hóa được kỳ vọng để khi tạo một giá trị mới rồi lập tức chuyển nó đi nhằm cấp phát giá trị đó trên heap, thì nó sẽ được tạo ngay từ đầu trên heap</i>. Ở đây cái tên 'tối ưu hóa' có thể gây hiểu lầm, nên đang có thảo luận về việc đổi tên

    • Có thể là tôi chưa hiểu đúng độ phức tạp của vấn đề, nhưng tôi nghĩ chỉ cần xác định một calling convention phù hợp là có thể giải quyết khá dễ. Nếu kích thước struct lớn hơn x hoặc có marker type, thì caller truyền một buffer bằng outref và callee ghi trực tiếp struct vào buffer đó. Làm vậy thì ngay cả khi viết code bình thường cũng có thể tránh cấp phát heap lặp lại, và trong các tình huống khác cũng giảm được các bản sao chép không cần thiết. Đây là chủ đề đã được đầu tư rất nhiều công sức, nên tôi lại tò mò vì sao các giải pháp được đề xuất dường như bất tiện hơn

    • Tôi nghĩ thay vì xử lý kiểu này như một tối ưu hóa nội bộ, sẽ trực quan hơn cho mọi người nếu biến nó thành thứ rõ ràng như một hàm new

    • Trong C++, kiểu semantic này được gọi là elision

    • Tôi đề xuất các tên như 'coalesced heap construction' hoặc 'coalesced heap allocation'

  • Mỗi khi nghe nói về các tính năng khác nhau của Rust, tôi lại đùa rằng "ít nhất xin đừng làm chuyện nhét tokio vào kernel". Nếu Rust phát triển đủ mạnh và xuất hiện direct composition renderer để có thể tạo các ứng dụng chạy trên toàn bộ kernel, thì đó cũng có thể là một tình huống khá thú vị

    • Thực ra việc triển khai async runtime trong kernel là chuyện cực kỳ trivial. Nói cho cùng thì workqueue của kernel bản thân nó đã là một runtime rồi

    • Nếu không phải nói đùa thì đó là hiểu sai tận gốc về cấu trúc khi viết mã kernel bằng Rust (và C). Khi code trong kernel thì cũng như C stdlib, Rust chạy ở chế độ no_std, không dùng được cargo hay crates. Muốn dùng tokio thì phải viết lại một nửa, thay toàn bộ phần tương tác với OS như socket sang kiểu của kernel

  • Tôi nghĩ các tính năng Rust lần này đi vào Linux là những tính năng đầu tiên hữu ích rộng rãi cho chính ngôn ngữ Rust, chứ không chỉ giới hạn ở kernel. Có cảm giác rằng việc phát triển tính năng quá xoay quanh kernel trước đây đã phần nào cản trở việc phát triển các tính năng ngôn ngữ/thư viện khác

    • Theo tôi biết thì systems programming là lĩnh vực ưu tiên áp dụng Rust. Khả năng tương tác là điều cốt lõi trong OS, embedded hay các hệ thống phức tạp dựa trên C. Các tính năng lần này thực ra không dành riêng cho kernel mà có vẻ giống các utility mang tính tổng quát, rất cần thiết cho systems programming trong thực tế

    • Những tiến triển phục vụ phát triển kernel/firmware đang diễn ra ở nhiều nơi, nhưng không phải lúc nào cũng trở thành chủ đề được mọi người chú ý. Philipp đặc biệt đang thúc đẩy thay đổi lớn trong lĩnh vực này

    • Vai trò chính của Rust là low-level systems programming. Ở các lĩnh vực khác, các ngôn ngữ managed biên dịch cho userspace là lựa chọn tốt hơn nhiều, và trong các hệ thống được cấu thành như Self, Inferno hay kiến trúc Android, tôi nghĩ việc tập trung vào các tính năng low-level kiểu C này cũng không có vấn đề gì

  • Các tính năng này rất hay vì không chỉ giúp cho kernel mà còn có ích ở các lĩnh vực khác nữa (đặc biệt là generalized projections). Tôi rất hài lòng khi thấy Linux đang thúc đẩy sự phát triển của ngôn ngữ Rust

  • Tôi tò mò không biết có nghiên cứu/công cụ nào dùng LLM để tự động chuyển code C sang Rust hay không. Tôi đang nghĩ liệu có thể để LLM tạo code Rust cho chat, usb, i2c, GPU driver rồi build/test luôn hay không, hoặc thử trên những dự án 'nhỏ hơn' như sqlite, apache, nginx

    • Ngoài hướng dùng LLM thì cũng có dự án c2rust với các trường hợp áp dụng thực tế. LLM về cơ bản vẫn chỉ dừng ở mức approximation nên không làm chính xác được, và tạo ra quá nhiều lỗi tinh vi. Nếu không kết hợp với các phương pháp hình thức như formal method thì không thực tế. Chỉ unit test thôi cũng có rất nhiều vấn đề không phát hiện ra được. Và các ví dụ bạn nêu là các dự án 'nhỏ hơn' thực ra cũng không hề nhỏ. Xem thêm các trường hợp áp dụng thực tế

    • Darpa cũng quan tâm đến hướng nghiên cứu này và đã tài trợ, nhưng vẫn chưa đến giai đoạn có kết quả cụ thể

 
ahwjdekf 2025-10-17

Sự cuồng tín về căn chỉnh (alignment in dogmatism)