Miguel Ojeda, autor projektu Rust-for-Linux, zasugerował, aby deweloperzy jądra Linux rozważyli wydanie v6 komponentów do tworzenia sterowników urządzeń w języku Rust. To siódma edycja poprawek, uwzględniająca pierwszą wersję opublikowaną bez numeru wersji. Wsparcie dla Rust jest postrzegane jako eksperymentalne, ale zostało już włączone do gałęzi linux-next i jest na tyle rozwinięte, że można zacząć pracować nad warstwami abstrakcji nad subsystemami jądra oraz nad pisaniem sterowników i modułów. Rozwój jest finansowany przez firmę Google oraz organizację ISRG (Internet Security Research Group), która jest założycielem projektu Let’s Encrypt i wspiera rozwój HTTPS oraz technologii zwiększających bezpieczeństwo internetu.
W nowej wersji:
- Narzędzia oraz wersja biblioteki alloc, pozbawione możliwych generacji stanu „panic” w przypadku błędów, zostały zaktualizowane do wydania Rust 1.60, w której ustabilizowano wsparcie dla trybu „maybe_uninit_extra”, stosowanego w poprawkach do jądra.
- Dodano możliwość wykonywania testów z dokumentacji (testy, które jednocześnie są przykładami w dokumentacji), poprzez przekształcenie podczas kompilacji testów związanych z API jądra w testy KUnit, wykonywane podczas ładowania jądra.
- Przyjęto wymagania, zgodnie z którymi testy nie powinny generować ostrzeżeń lintera Clippy, tak jak kod dla jądra w języku Rust.
- Zaproponowano początkową implementację modułu „net” z funkcjami sieciowymi. Kod w języku Rust ma dostęp do takich struktur sieciowych jądra jak „Namespace” (oparty na strukturze jądra „struct net”), SkBuff (struct sk_buff), TcpListener, TcpStream (struct socket), Ipv4Addr (struct in_addr), SocketAddrV4 (struct sockaddr_in) i ich odpowiedników dla IPv6.
- Wdrożono początkowe wsparcie dla metod programowania asynchronicznego (async), zrealizowane w formie modułu kasync. Na przykład można tworzyć działający w trybie asynchronicznym kod do manipulacji TCP-socketami: async fn echo_server(stream: TcpStream) -> Result { let mut buf = [0u8; 1024]; loop { let n = stream.read(&mut buf).await?; if n == 0 { return Ok(()); } stream.write_all(&buf[..n]).await?; } }
- Dodano moduł net::filter do manipulacji filtrami pakietów sieciowych. Dodano przykład rust_netfilter.rs z implementacją filtra w języku Rust.
- Dodano wdrożenie prostego mutexa smutex::Mutex, które nie wymaga przypinania (pinning).
- Dodano blokadę NoWaitLock, która nigdy nie powoduje oczekiwania na zwolnienie, a w przypadku zajęcia przez inny wątek zgłasza błąd podczas próby uzyskania blokady zamiast zatrzymywać wywołującego.
- Dodano blokadę RawSpinLock, utożsamianą z raw_spinlock_t w jądrze, stosowaną w sekcjach, które nie mogą znajdować się w stanie oczekiwania.
- Dodano typ ARef dla referencji do obiektu, do którego zastosowano mechanizm zliczania referencji (always-refcounted).
- W backendzie rustc_codegen_gcc, umożliwiającym korzystanie z biblioteki libgccjit z projektu GCC jako generatora kodu w rustc dla zapewnienia w rustc wsparcia dla dostępnych w GCC architektur i optymalizacji, wdrożono możliwość uruchomienia kompilatora (bootstrapping) rustc. Uruchomienie kompilatora oznacza możliwość użycia w rustc generatora kodu opartego na GCC do zbudowania samego kompilatora rustc. Ponadto w ostatnim wydaniu GCC 12.1 wprowadzono poprawki w libgccjit, potrzebne do prawidłowego działania rustc_codegen_gcc. Trwają przygotowania do udostępnienia możliwości instalacji rustc_codegen_gcc za pomocą narzędzia rustup.
- Zauważono postęp w rozwoju frontendu GCC gccrs z implementacją kompilatora języka Rust opartego na GCC. Obecnie nad gccrs w trybie pełnego działania pracuje dwóch programistów.
Przypomnijmy, że proponowane zmiany umożliwiają użycie Rust jako drugiego języka do tworzenia sterowników i modułów jądra. Obsługa Rust jest przedstawiana jako opcja, nieaktywna domyślnie i nie prowadząca do włączenia Rust do obowiązkowych zależności kompilacyjnych jądra. Użycie Rust do tworzenia sterowników pozwoli na minimalnym wysiłku tworzyć bezpieczne i lepszej jakości sterowniki, wolne od problemów takich jak odwołania do zwolnionej pamięci, dereferencja wskaźników null oraz przekroczenia granic bufora.
Bezpieczna praca z pamięcią w języku Rust jest zapewniana w czasie kompilacji poprzez sprawdzanie referencji, śledzenie własności obiektów oraz uwzględnianie czasu życia obiektów (zakresu widoczności), a także poprzez ocenę poprawności dostępu do pamięci w czasie wykonywania kodu. Rust zapewnia również środki ochrony przed przepełnieniami wartości całkowitych, wymaga obowiązkowego inicjowania wartości zmiennych przed ich użyciem, lepiej obsługuje błędy w standardowej bibliotece, stosuje koncepcję niezmienności (immutable) referencji i zmiennych domyślnie oraz oferuje silną statyczną typizację w celu minimalizacji błędów logicznych.
Źródło: opennet.ru
