Uscita di Rust 1.96. Valutazione dell'idoneità di Rust per la creazione di firmware per microcontrollori

È stato rilasciato il linguaggio di programmazione Rust 1.96, originariamente sviluppato da Mozilla, ma attualmente mantenuto sotto l'egida dell'organizzazione no-profit indipendente Rust Foundation. Il linguaggio è focalizzato sulla gestione sicura della memoria e fornisce strumenti per raggiungere un elevato parallelismo nell'esecuzione dei compiti, evitando allo stesso tempo l'uso di un garbage collector e di un runtime (il runtime si limita a una base di inizializzazione e al supporto della libreria standard).

I metodi di gestione della memoria in Rust mirano a evitare errori nella manipolazione dei puntatori e a proteggere da problemi derivanti dal lavoro a basso livello con la memoria, come l'accesso a porzioni di memoria dopo che sono state liberate, la dereferenziazione di puntatori nulli, l'uscita dai limiti del buffer, ecc. Per la distribuzione delle librerie, la compilazione e la gestione delle dipendenze, viene sviluppato il gestore di pacchetti Cargo. È supportato un repository per la pubblicazione delle librerie, crates.io.

La gestione sicura della memoria in Rust è garantita durante la compilazione attraverso il controllo dei riferimenti, il tracciamento della proprietà degli oggetti, la considerazione del tempo di vita degli oggetti (ambiti di visibilità) e la valutazione della correttezza dell'accesso alla memoria durante l'esecuzione del codice. Rust fornisce anche strumenti per proteggere da overflow interi, richiede l'inizializzazione obbligatoria delle variabili prima dell'uso, gestisce meglio gli errori nella libreria standard, applica il concetto di riferimenti e variabili immutabili per impostazione predefinita e offre una forte tipizzazione statica per minimizzare gli errori logici.

Novità principali:

  • È stato aggiunto il modulo range con l'implementazione di nuovi tipi, sviluppati per sostituire i tipi obsoleti Range, RangeInclusive, RangeToInclusive e RangeFrom, e che consentono di memorizzare intervalli in strutture Copy. Il tipo Range definisce intervalli limitati da un valore minimo e massimo consentito (esclusi), il tipo RangeFrom definisce numeri a partire da un valore specificato, mentre il tipo RangeInclusive definisce i valori dell'intervallo specificato includendo entrambi i suoi confini. Nelle future versioni saranno introdotti i tipi RangeFull e RangeTo, mentre la vecchia implementazione sarà trasferita in core::range::legacy::*, e la sintassi «N..M» sarà convertita nella nuova variante dei tipi.

    I nuovi tipi si distinguono per il fatto che implementano il trait IntoIterator invece del trait Iterator, cioè invece di un iteratore incorporato definiscono come trasformare un tipo in un iteratore. Questo approccio consente di utilizzare l'operazione di copia (il trait Copy, che indica che i valori di un tipo possono essere duplicati tramite semplice copia), che in precedenza non era disponibile a causa di incompatibilità con i tipi dotati di iteratori incorporati.
    Ad esempio, i nuovi tipi consentono di memorizzare i confini di un array in una struttura che viene copiata interamente senza dover salvare separatamente i valori iniziale e finale:

    use core::range::Range;

    #[derive(Clone, Copy)]
    pub struct Span(Range);

    impl Span {
    pub fn of(self, s: &str) -> &str {
    &s[self.0]
    }
    }

  • Sono stati aggiunti i macro «assert_matches!» e «debug_assert_matches!», che controllano la corrispondenza di un valore con il modello specificato e terminano in modo anomalo l'esecuzione in caso di discrepanza. Rispetto alle espressioni «assert!(matches!(..))» e «debug_assert!(matches!(..))», i nuovi macro si differenziano per la generazione di informazioni di debug con i valori che hanno causato il fallimento. Per evitare conflitti con macro di terze parti con nomi simili, i nuovi macro richiedono l'importazione esplicita della libreria «core::assert_matches».

    use core::assert_matches;

    fn get_random_number() -> u32 {
    4
    }

    fn main() {
    assert_matches!(get_random_number(), 1..=6);
    }

  • Durante la compilazione per la piattaforma target WebAssembly, è stata interrotta la trasmissione dell'opzione del linker «—allow-undefined», che consentiva il collegamento in presenza di simboli indefiniti, che venivano convertiti in importazione dal modulo «env». Durante la compilazione per WebAssembly, tutti i simboli associati al collegamento devono ora essere definiti per impostazione predefinita. Per ripristinare il comportamento precedente, è possibile utilizzare la variabile d'ambiente «RUSTFLAGS=-Clink-arg=—allow-undefined» o l'espressione ‘#[link(wasm_import_module = «env»)]’ nel codice.
  • Una nuova serie di API è stata trasformata in versioni stabili, inclusi i metodi stabilizzati e le implementazioni delle trait:
    • assert_matches!
    • debug_assert_matches!
    • From per AssertUnwindSafe
    • From per LazyCell
    • From per LazyLock
    • core::range::RangeToInclusive
    • core::range::RangeToInclusiveIter
    • core::range::RangeFrom
    • core::range::RangeFromIter
    • core::range::Range
    • core::range::RangeIter
  • Nel gestore di pacchetti Cargo è stata eliminata la vulnerabilità CVE-2026-5223, che può essere utilizzata per sovrascrivere il codice sorgente di un altro pacchetto crate nella cache locale dei pacchetti dallo stesso repository tramite manipolazioni con collegamenti simbolici all'interno del pacchetto crate. La vulnerabilità si manifesta solo quando si lavora con repository di pacchetti esterni e non riguarda gli utenti del repository crates.io, poiché in crates.io è vietato caricare pacchetti con collegamenti simbolici.

È possibile notare anche la pubblicazione (PDF) dei risultati dell'analisi dell'idoneità del linguaggio Rust per lo sviluppo di firmware per microcontrollori e sistemi embedded a risorse limitate.
Lo studio è stato condotto dall'azienda STMicroelectronics con la partecipazione di diverse università europee. Due team di sviluppatori isolati sono stati incaricati di implementare lo stesso firmware per i microcontrollori STM32U585AI con processore Arm Cortex-M33. Il primo team ha creato il firmware in C, mentre il secondo in Rust.

I test del lavoro effettuato non hanno rivelato vantaggi significativi nell'utilizzo del linguaggio C rispetto a Rust nello sviluppo di firmware per microcontrollori, confrontando l'uso della memoria e le prestazioni. Inoltre, l'utilizzo di un runtime di sistema scritto in Rust del progetto aperto Ariel OS ha consentito di ottenere un consumo di memoria nel progetto Rust inferiore rispetto all'implementazione in linguaggio C, che utilizza uno stack tradizionale per lo sviluppo di firmware basato sulla libreria newlib.

La dimensione del firmware risultante è stata di 84100 byte per il progetto in Rust e 76744 byte per il progetto in C (inferiore del 10%), ma il consumo di memoria RAM nel firmware in Rust si è rivelato significativamente più basso: 24640 byte contro 42608 byte. Per quanto riguarda le prestazioni, durante i test dei prototipi iniziali, sviluppati in 6 settimane, l'implementazione in Rust ha superato di due volte quella in C, ma entrambe le implementazioni hanno mostrato prestazioni significativamente inferiori a quelle massime calcolate. Dopo 4 settimane dedicate all'ottimizzazione, entrambe le implementazioni hanno raggiunto risultati simili, vicini al massimo calcolato.



Fonte: opennet.ru
Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster