Rust — будущее системного программирования

Не так давно компания Google объявила, что в Android теперь поддерживается язык программирования Rust. В этой статье мы хотим показать, как язык Rust становится востребованным в разработке ядра Linux, в программировании микроконтроллеров и зачем нужен Rust и его польза для всей индустрии Embedded. В этом статье на нескольких простых примерах рассмотрим технические аспекты языка Rust для Embedded.

Rust – это язык системного программирования, предназначенный для обеспечения безопасности, скорости и параллелизма. Rust имеет множество функций времени и безопасности во время компиляции, чтобы избежать сбоев данных и общих ошибок, все с минимальными издержками до нуля. Язык сфокусирован на безопасной работе с памятью, обеспечивает автоматическое управление памятью и предоставляет средства для достижения высокого параллелизма выполнения заданий, при этом обходясь без использования сборщика мусора и runtime. Автоматическое управление памятью в Rust избавляет разработчика от манипулирования указателями и защищает от проблем, возникающих из-за низкоуровневой работы с памятью, таких как обращение к области памяти после её освобождения, разыменование нулевых указателей, выход за границы буфера и т.п. Для распространения библиотек, обеспечения сборки и управления зависимостями проектом развивается пакетный менеджер Cargo, позволяющий получить нужные для программы библиотеки в один клик. Cargo – это инструмент, который позволяет указывать необходимые зависимости для проектов на языке Rust и убедиться, что вы получите воспроизводимые сборки.

У Rust много плюсов:

  • Отличная статическая типизация;
  • Отсутствие сборщика мусора и возможность контролировать место размещения данных в памяти;
  • Отличный встроенный статический анализатор кода, который позволяет избегать ошибок, связанных с управлением памятью и многопоточностью;
  • Понятный синтаксис;
  • Компилятор от разработчиков Rust со встроенным менеджером и сборщиком пакетов, системой тестов и генератором документации;
  • Безопасная работа с памятью;
  • Возможность применять абстракции;
  • Для многих ошибок во время компиляции приводятся варианты исправления;
  • Указатели можно использовать только в небезопасном коде, в безопасном коде применяются исключительно ссылки на гарантированно существующие объекты;
  • Очень строгий компилятор кода;
  • Предсказуемое выделение и освобождение памяти;
  • Замыкания;
  • Сопоставление с образцом;
  • Алгебраические типы данных и т.п.

Rust для программирования микроконтроллеров

Уже сегодня язык Rust в компании ShuraCore является любимым языком программирования у разработчиков, все больше клиентов при разработке ПО хотят видеть Rust, как базовый язык разработки софта, Embedded не исключение. Вот несколько пунктов почему Rust уже равный конкурент C/C++ в Embedded.

  1. Мощный статический анализ. Принудительная настройка контактов и периферийных устройств во время компиляции. Гарантия того, что ресурсы не будут использоваться не предназначенными частями приложения.
  2. Гибкая память. Динамическое распределение памяти не является обязательным. Используйте глобальный распределитель и динамические структуры данных. Или вообще исключить кучу и статически распределить всё.
  3. Написание параллельного кода без страха. Rust делает невозможным случайное разделение состояния между потоками. Используйте любые подходы к параллелизму, которые вам нравятся, и вы всё равно получите строгие гарантии Rust.
  4. Совместимость. Интегрируйте Rust в вашу существующую кодовую базу на C или используйте существующий SDK для написания приложения на Rust.
  5. Переносимость. Один раз напишите библиотеку или драйвер и используйте его с разными системами начиная от очень маленьких микроконтроллеров, до мощных интегрированных плат.
  6. Движимый сообществом. В рамках open source проекта Rust, поддержка встраиваемых систем движется, при поддержке коммерческих партнёров, лучшим в своём классе open source сообществом.

Мы подготовили небольшой пример мигания светодиодами на отладочной плате STM32f429i-disco.

				
					cargo-features = ["default-run"]

[package]
authors = ["ShuraCore info@shuracore.com"]
categories = ["embedded", "no-std"]
name = "stm32f429i_disco"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = "0.6.2"
cortex-m-rt = "0.6.12"
panic-halt = "0.2.0"

[dependencies.stm32f4]
version = "0.10.0"
features = ["stm32f429", "rt"]

[dependencies.stm32f4xx-hal]
version = "0.7"
features = ["rt", "stm32f429"]
				
			
				
					#![deny(unsafe_code)]
#![no_main]
#![no_std]

// Halt on panic
#[allow(unused_extern_crates)] 
extern crate panic_halt; // panic handler

use cortex_m;
use cortex_m_rt::entry;
use stm32f4xx_hal as hal;

use crate::hal::{prelude::*, stm32};

#[entry]
fn main() -> ! {
    if let (Some(dp), Some(cp)) = (
        stm32::Peripherals::take(),
        cortex_m::peripheral::Peripherals::take(),
    ) {
        // Set up the LEDs. On the stm32f429i-disco they are connected to pin PG13 and PG14.
        let gpiog = dp.GPIOG.split();
        let mut led3 = gpiog.pg13.into_push_pull_output();
        let mut led4 = gpiog.pg14.into_push_pull_output();

        // Set up the system clock. We want to run at 180MHz for this one.
        let rcc = dp.RCC.constrain();
        let clocks = rcc.cfgr.sysclk(180.mhz()).freeze();

        // Create a delay abstraction based on SysTick
        let mut delay = hal::delay::Delay::new(cp.SYST, clocks);

        loop {
            // On for 1s, off for 1s.
            led3.set_high().unwrap();
            led4.set_low().unwrap();
            delay.delay_ms(1000_u32);
            
            led3.set_low().unwrap();
            led4.set_high().unwrap();
            delay.delay_ms(1000_u32);
        }
    }

    loop {}
}
				
			

Rust для разработки драйверов Linux

В 2020 году разработчики ядра Linux предложили использовать Rust для разработки нового кода. В марте 2021 года эта идея была частично реализована — в состав ветки linux-next, на которой базироваться Linux 5.13, включили начальный набор компонентов для разработки драйверов устройств на Rust. Корпорация Google уже заявила о намерении принять участие в инициативе по продвижению поддержки Rust в ядро Linux. Компания привела примеры целесообразности внедрения Rust для борьбы с проблемами, которые возникают из-за ошибок при работе с памятью. Представители компании также считают, что Rust вполне готов присоединиться к C, став еще одним языком разработки компонентов ядра Linux.

Вашему вниманию пример драйвера для Linux на языке Rust.

[package]
name = "test_example"
version = "0.1.0"
authors = ["ShuraCore <info@shuracore.com>"]
edition = "2018"

[lib]
crate-type = ["staticlib"]

[dependencies]
linux-kernel-module = { path = ".." }

[profile.release]
panic = "abort"
lto = true

[profile.dev]
panic = "abort"

#![no_std]
#![feature(alloc)]

extern crate alloc;
use crate::alloc::string::{String, ToString};
use linux_kernel_module::c_types;
use linux_kernel_module::println;

struct ShuraCoreModule {
    message: String,
}

impl linux_kernel_module::KernelModule for ShuraCoreModule {
    fn init() -> linux_kernel_module::KernelResult {
        println!("Hello from ShuraCore!");
        Ok(ShuraCoreModule {
            message: "Hello ShuraCore!".to_string(),
        })
    }
}

impl Drop for ShuraCoreModule {
    fn drop(&mut self) {
        println!("Goodbye from ShuraCore!");
    }
}

static mut MODULE: Option = None;

#[no_mangle]
pub extern "C" fn init_module() -> c_types::c_int {
    match ::init() {
        Ok(m) => {
            unsafe {
                MODULE = Some(m);
            }
            return 0;
        }
        Err(_e) => {
            return 1;
        }
    }
}

#[no_mangle]
pub extern "C" fn cleanup_module() {
    unsafe {
        MODULE = None;
    }
}

#[link_section = ".modinfo"]
pub static MODINFO: [u8; 12] = *b"license=GPL\0";

Статистика

В тенденциях Google вы можете увидеть, как результаты поиска Rust растут из года в год, все потому что у Rust народная любовь.

Когда дело доходит до популярности, Rust на первом месте. С 2015 года Rust был признан разработчиками самым любимым языком программирования в опросе разработчиков Stack Overflow пять лет подряд (2016, 2017, 2018, 2019, 2020):

Все больше и больше корпораций и компаний используют Rust в коммерческой разработке, вот их небольшая часть: Dropbox, Coursera, Figma, npm, Microsoft, Cloudflare, Facebook, Amazon, Discord и другие крупные игроки. По официальной статистике уже более 300 компаний по всему миру используют Rust в коммерческой разработке.

Итого, Rust – это язык системного программирования, который сочетает в себе гарантии надёжности и корректности процесса формирования программного обеспечения во время компиляции с высокой производительностью. Он улучшает идеи других системных языков, таких как С/C++, обеспечивая  при этом гарантированную безопасность памяти (без сбоев, без скачков данных) и полный контроль над жизненным циклом памяти. Цель Rust – показать высокую продуктивность программного обеспечения в конкретных областях использования. Наша команда специалистов использует Rust в качестве языка программирования для создания системного программного обеспечения нового уровня со взглядом на завтрашний день. Инженеры ШураКор разрабатывают ПО для следующих областей применения:

Связаться с нами
Контакты

Республика Беларусь, г. Минск

220053, ул. Нововиленская, д.38, каб. 11

ООО “ШураКор”, УНП 193520488

ООО “ШураКор” 2021 – 2024 © Все права защищены