Шоста версія патчів для ядра Linux з підтримкою мови Rust

Мігель Охеда (Miguel Ojeda), автор проекту Rust-for-Linux, запропонував для розгляду розробниками ядра Linux випуску v6 компонентів для розробки драйверів пристроїв на мові Rust. Це сьома редакція патчів з урахуванням першого варіанта, опублікованого без версії. Підтримка Rust розглядається як експериментальна, але вже включена у гілку linux-next і досить розвинена для початку роботи зі створення шарів абстракції над підсистемами ядра, а також для написання драйверів та модулів. Розробка фінансується компанією Google та організацією ISRG (Internet Security Research Group), яка є засновником проекту Let's Encrypt та сприяє просуванню HTTPS та розвитку технологій для підвищення захищеності інтернету.

В новой версії:

  • Інструментарій та варіант бібліотеки alloc, позбавлений можливих генерацій стану "panic" при виникненні помилок, оновлені до випуску Rust 1.60, в якій стабілізована підтримка режиму "maybe_uninit_extra", що застосовується в патчах до ядра.
  • Додано можливість виконання тестів з документації (тести, що одночасно використовуються як приклади в документації), через перетворення під час компіляції тестів, зав'язаних на API ядра, в тести KUnit, що виконуються під час завантаження ядра.
  • Прийнято вимоги, відповідно до яких тести не повинні призводити до виведення попередження лінтера Clippy, як і код для ядра мовою Rust.
  • Запропоновано початкову реалізацію модуля «net» з мережевими функціями. Для коду на мові Rust надано доступ до таких мережевих структур ядра, як Namespace (на основі структури ядра struct net), SkBuff (struct sk_buff), TcpListener, TcpStream (struct socket), Ipv4Addr (struct in_addr), SocketAddrV4 ( struct sockaddr_in) та їх еквівалентам для IPv6.
  • Реалізовано початкову підтримку методів асинхронного програмування (async), реалізовано у формі модуля kasync. Наприклад, можна створювати код, що працює в асинхронному режимі, для маніпуляції з TCP-сокетами: 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?; } }
  • Доданий модуль net::filter для маніпуляції із фільтрами мережевих пакетів. Доданий приклад rust_netfilter.rs з реалізацією фільтра мовою Rust.
  • Додано реалізацію простого м'ютексу smutex::Mutex, що не вимагає прив'язки (pinning).
  • Додано блокування NoWaitLock, яке ніколи не призводить до очікування звільнення, а у разі зайняття іншим потоком призводить до виведення помилки при спробі отримання блокування замість зупинки викликаючого.
  • Додане блокування RawSpinLock ототожнене з raw_spinlock_t в ядрі, що застосовується до секцій, які не можуть перебувати в стані очікування.
  • Доданий тип ARef для посилань на об'єкт, до якого застосовується механізм підрахунку посилань (always-refcounted).
  • У бекенді rustc_codegen_gcc, що дозволяє використовувати бібліотеку libgccjit від проекту GCC як генератор коду в rustc для забезпечення rustc підтримки доступних в GCC архітектур і оптимізації, реалізована можливість розкрутки компілятора (bootstrapping) rustc. Під розкручуванням компілятора розуміється можливість використання в rustc генератора коду на основі GCC для збирання самого компілятора rustc. Крім того, до недавнього випуску GCC 12.1 включені виправлення в libgccjit, необхідні для коректної роботи rustc_codegen_gcc. Підготовка до надання можливості установки rustc_codegen_gcc за допомогою утиліти rustup.
  • Наголошується на прогресі розробки GCC-фронтенду gccrs з реалізацією компілятора мови Rust на базі GCC. В даний час над gccrs в режимі повного робітника працюють два розробники.

Нагадаємо, що запропоновані зміни дають можливість використовувати Rust як другу мову для розробки драйверів та модулів ядра. Підтримка Rust подається як опція, не активна за замовчуванням і не призводить до включення Rust до обов'язкових складальних залежностей до ядра. Використання Rust для розробки драйверів дозволить з мінімальними зусиллями створювати безпечні та якісніші драйвери, позбавлені таких проблем як звернення до області пам'яті після її звільнення, розіменування нульових покажчиків та вихід за межі буфера.

Безпечна робота з пам'яттю забезпечується в Rust під час компіляції через перевірку посилань, відстеження володіння об'єктами та облік часу життя об'єктів (області видимості), а також оцінку коректності доступу до пам'яті під час виконання коду. Rust також надає засоби для захисту від цілих переповнень, вимагає обов'язкової ініціалізації значень змінних перед використанням, краще обробляє помилки в стандартній бібліотеці, застосовує концепцію незмінності посилань і змінних за умовчанням, пропонує сильну статичну типізацію для мінімізації логічних помилок.

Джерело: opennet.ru

Додати коментар або відгук