Во время прошлогодней Linux Plumbers Conference 2021 один из мейнтейнеров, Мигель Охеда, задался вопросом: нужен ли сообществу Rust в коде ядра Linux и что нужно для того, чтобы соответствующие патчи были приняты в древе проекта? Комментарии от разработчиков были в основном доброжелательными, но без фанатизма. Лидер проекта Линус Торвальдс сказал, что не против т․ н․ пилотной серии патчей на Rust, с оговоркой, что и остальные разработчики должны рассматривать их в качестве опытной партии.

Тут уместно вспомнить, что ядро Linux вероятно один из самых масштабных проектов с открытым исходным кодом и самый успешный, учитывая пройденный путь за более, чем 30 лет после опубликования версии ядра 0.01. Всё это время разработка велась и ведётся поныне на языке программирования C. Линус Торвальдс без ума от C и не раз высказывался в том духе, что от добра добра не ищут, и все остальные ЯП непригодны для разработки ядра.


Мне нравится разбираться с железом и для этой цели C нет равных.
I like interacting with hardware from a software perspective. And I have yet to see a language that comes even close to C…​When I read C, I know what the assembly language will look like.
Линус Торвальдс 2012


Быстрый, низкоуровневый и традиционно один из самых востребованных языков программирования, разве C нужны дополнительные подпорки в коде ядра? Что может предложить Rust такого, чтобы вся затея в итоге оправдала себя? Если в двух словах, то всё дело в НП, то есть в неопределённом поведении, характерном для некоторых типичных сценариев в C. Такое поведение зачастую оборачивается ошибками в коде и скрытыми уязвимостями, в то время как Rust архитектурно защищён от НП и связанных с ним проблем.

Согласно последнему рабочему документу C, неопределённое поведение возникает при использовании ошибочной программной конструкции, или данных, и данный документ для таких сценариев не предъявляет никаких требований. Примером такого рода является поведение при разыменовании нулевого указателя. Такого же поведения можно добиться, если значение первого оператора равно INT_MIN, или второго оператора — равно 0.

int f(int a, int b) {
 	return a / b;
}

Для того чтобы исправить НП, нужно задать условия выхода.

int f(int a, int b) {
  if (b == 0)
	abort();
if (a == INT_MIN && b == -1)
abort();
return a / b;
}

Неопределенное поведение проявляется в нарушениях безопасного использования памяти, например, к ошибкам связанным с переполнением буфера, чтением, или записи за пределами буфера, использование освобождённой памяти (use-after-free) и др. Из недавних примеров можно вспомнить уязвимость записи за пределами буфера WannaCry. Туда же следует отнести Stagefright на ОС Android. Анализ 0-day дыр безопасности компании Гугл показал, что 80% из них вызваны нарушением безопасного доступа к памяти. Ниже на картинке ещё один результат fuzzing-проверки по разным проектам.

Figure 1. Соотношение по дырам безопасности в проектах на разных языках программирования.

Чтобы не быть голословными, рассмотрим на примере:

#include <stdlib.h>
int main(void)
{
int * const a = malloc(sizeof(int));
if (a == NULL)
abort();
*a = 42;
free(a);
free(a);
}

Несмотря на явную оплошность с двойным освобождением памяти, компилятор не прерывает работу. Таким образом, программа может быть запущена, хоть и завершится с ошибкой.

|13:59:54|adm@redeye:[~]> gcc -g -Wall -std=c99 -o test test.c
|13:59:59|adm@redeye:[~]> echo $?
0
|14:00:05|adm@redeye:[~]> ./test
free(): double free detected in tcache 2
Aborted

Проверим теперь поведение точно такого же кода на Rust.

pub fn main() {
let a = Box::new(42);
drop(a);
println!("{}", *a);
}

На этапе компиляции программа выдаст ошибку из-за того, что память в переменной была высвобождена. Текст содержит описание и ссылку с кодом ошибки.

rustc app.rs
error[E0382]: borrow of moved value: a
--> app.rs:4:17
|
2 |  	let a = Box::new(42);
|      	- move occurs because a has type std::boxed::Box<i32>, which does not implement the Copy trait
3 |   	drop(a);
|        	- value moved here
4 | 	println!("{}", *a);
|                	^^ value borrowed here after move
error: aborting due to previous error
For more information about this error, try rustc --explain E0382.rustc app.rs

Преимущества Rust не ограничиваются безопасным доступом к памяти, есть ряд других полезных свойств, которые могли бы облегчить труд разработчиков ядра Linux. Взять хотя бы инструментарий для управления зависимостями. Много-ли тех, кому по душе сражаться с include путями в заголовочных файлах, раз за разом запускать pkg-config вручную, либо через макросы Autotools, полагаться на то, что пользователь установит нужные версии библиотек? Разве не проще записать всё необходимое в файл Cargo.toml, перечислив в нём названия и версии всех зависимостей? При запуске cargo build они автоматически подтянутся из реестра пакетов crates.io.

В ядро Linux код попадает не сразу, а после тщательной проверки качества и соответствия внутренним стандартам. Исключения крайне редки, а это подразумевает необходимость часто тестировать программу на наличие возможных ошибок и дефектов. Сложность, или неудобство связанные с тестированием кода напрямую будут сказываться на результате работы. Так уж получилось, что язык С по сегодняшним меркам неважно приспособлен для всестороннего тестирования по ряду причин.

  • Немалые трудности представляет обработка сценариев с внутренними статическими функциями. Их можно вызвать лишь в самом файле, где они определены. Для того, чтобы до них добраться извне, нужно писать #include директивы, либо же использовать условия #ifdef.
  • Для того чтобы слинковать часть зависимостей с тестовой программой необходимо творчески редактировать Makefile, или CMakeLists.txt.
  • Нужно выбрать из множества фреймворков какой-то один, либо несколько самых популярных. Придётся их освоить, дабы уметь интегрировать свой проект и запускать автоматические проверки.

И всего этого можно избежать, написав в Rust:

#[test]
fn test_foo_prime() {
assert!(foo() == expected_result);
}

Вместе с тем, явная ошибка считать, что применение Rust в коде Linux лишено недостатков. Во-первых, одним дистиллированно безопасным кодом ядро написать не выйдет, во всяком случае, таковы реалии Linux. Иногда нужно переступить через порог безопасности, например, при статическом считывании и вычислении адресов регистров CPU.

Во-вторых, из-за дополнительных рантайм проверок кое-где могут возникнуть проблемы с производительностью и с высокой степенью вероятности это будут именно те редкие фрагменты кода, где сложно соответствовать принятым стандартам безопасности.

И наконец в третьих нельзя просто так взять и переписать код на другом ЯП из-за очевидных и неизбежных организационных проблем.

Rust в ядре, как это выглядит?


Так или иначе, Rust получил зелёный свет, пока что в ранге экспериментальной поддержки. Отправной точкой станет использование нового языка программирования при написании драйверов, если этот будет целесообразно. В частности, некоторые GPIO драйвера уже пишут на Rust. Использование Rust в стеке WiFi и Bluetooth драйверов также может пойти на пользу делу по мнению мейнтейнера kernel.org Kees Cook.

Если пройти по ссылке, то можно заметить, что код на Rust несколько компактней, но возможно тут немного срезаны углы и принятый стиль разработки Linux нарушен в плане игнорирования длин строк, несоблюдения конвенций наименования переменных и пр. Однако, если приглядеться поближе, есть и более существенные отличия.

	writeb(pl061->csave_regs.gpio_is, pl061->base + GPIOIS);
writeb(pl061->csave_regs.gpio_ibe, pl061->base + GPIOIBE);
writeb(pl061->csave_regs.gpio_iev, pl061->base + GPIOIEV);
writeb(pl061->csave_regs.gpio_ie, pl061->base + GPIOIE);

В этом фрагменте C кода происходит расчёт вручную некоего адреса внутри функции writeb и если сравнить с аналогичным фрагментом на Rust, то можно заметить, что там нет лазейки для произвольной записи в память за рамками смещения.

    	pl061.base.writeb(inner.csave_regs.gpio_is, GPIOIS);
pl061.base.writeb(inner.csave_regs.gpio_ibe, GPIOIBE);
pl061.base.writeb(inner.csave_regs.gpio_iev, GPIOIEV);
pl061.base.writeb(inner.csave_regs.gpio_ie, GPIOIE);

Документация проекта находится по адресу на Гитхабе. Сейчас ссылки на заголовочные include файлы C не работают. Rust имеет доступ к условной компиляции на основе конфигурации ядра.

#[cfg(CONFIG_X)] // CONFIG_X активен (y or m)
#[cfg(CONFIG_X="y")] // CONFIG_X активен и является встроенным (y)
#[cfg(CONFIG_X="m")] // CONFIG_X активен является модулем (m)
#[cfg(not(CONFIG_X))] // CONFIG_X не активен

На данный момент интеграция нового языка программирования выглядит так. Название kernel crate не должно пугать, это не реализация ядра на Rust, а всего лишь реализация необходимых абстракций. Прикладное средство bindgen является по сути парсером, который автоматически создаёт привязки для заголовочных файлов C. Bindgen считывает заголовки C и из них пишет соответствующие функции на Rust.

Figure 2. Rust в структуре каталогов ядра Linux

Так выглядит реализация драйверов Linux на Rust. Если идти справа налево, то в начале находится уже знакомый нам обработчик привязок C bindgen, правее и за кадром уже чистый и без примесей C код Linux-ядра. Далее следует kernel crate с требуемыми абстракциями, впрочем, это может быть какой-нибудь другой crate, или даже crates. Принципиальный момент заключается в том, что драйвер my_foo может использовать только безопасные абстракции из kernel crate. Драйвер не может напрямую обращаться к C-функциям. Благодаря такой двухступенчатой схеме подсистема обеспечивает безопасность кода Rust в Linux.

Figure 3. Принцип работы драйверов Rust

Поддержка реализована для следующих платформ.

  • arm (только armv6);
  • arm64;
  • powerpc (только ppc64le);
  • riscv (только riscv64);
  • x86_64.

7 патчей за 8 месяцев


В начале мая Мигель Охеда представил коллегам уже седьмую серию патчей для разработки Rust-драйверов, из которых первая была опубликована без номера версии, в статусе RFC. Таким образом это считается Patch v6. Проект получает финансирование со стороны Internet Security Research Group и компании Гугл. Несмотря на экспериментальный статус поддержка Rust уже позволяет разработчикам создавать слои абстракций для различных подсистем, работать над новыми драйверами и модулями. Список нестабильных функций и запросов все ещё внушительный, но работа над ним активно ведётся.

В этой серии патчей были следующие изменения.

▍ Инфраструктурные обновления


  • Инструментарий вместе с библиотекой alloc обновлены до версии Rust 1.60.
  • Rust имеет такую примечательную функциональность, как тестируемая документация. Работает это следующим способом. Программист вставляет в комментарии примеры кода с помощью разметки Markdown, а rustdoc умеет их запускать, как обычный тест. Это очень удобно, так как можно показывать, как используется данная функция и одновременно тестировать её.

/// /// fn foo() {} /// println!("Hello, World!"); ///

До Patch v6 нельзя было запускать тестируемую документацию с использованием API ядра, с новым патчем это стало возможным. Документация из kernel crate во время компиляции преобразуется в KUnit тесты и выполняется при загрузке ядра.

  • В соответствии с новыми требованиями в тесты не должны завершаться предупреждениями линтера Clippy.
  • В Rust подсистеме GCC rustc_codegen_gcc добавлена новая функциональность по самозагрузке компилятора. Это означает, что его можно использовать для сборки самого компилятора rustc. Кроме того, в GCC 12.1 включены исправления, необходимые для libgccjit.

▍ Абстракции и драйвера


  • Начальная поддержка сетевого стека в рамках модуля net.
  • Методы асинхронного программирования Rust можно использовать в ограниченных средах, включая ядро. В последнем патче появилась поддержка 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.
  • Добавлен простой мютекс mutex::Mutex, не требующий привязки. Это довольно удобно, не смотря на то, что по функционалу мютекс уступает своему аналогу на C.
  • Новый механизм блокировки NoWaitLock, который в соответствии с названием, никогда не приводит к ситуации ожидания ресурса. Если ресурс занят другим потоком, ядром CPU, то попытка блокировки завершится ошибкой, а не остановкой вызывающего.
  • Ещё одна блокировка RawSpiLock, на основе C-эквивалента raw_spinlock_t, предназначена для фрагментов кода, где приостановка абсолютно недопустима.
  • Для тех объектов, по отношению к которым всегда подсчитывается количество ссылок (a. k. a. always-refcounted), создан новый тип ARef. Его область применения — облегчить определение надстроек существующих C-структур.

▍ Дополнительные материалы




Комментарии (144)


  1. AnthonyMikh
    14.06.2022 12:51
    +8

    Ну и где плашка о том, что это перевод? Ну не мог шарящий человек скопировать сниппеты кода без отступов и писать "НП" вместо "UB".


    1. dlinyj
      14.06.2022 14:13
      +4

      А что не так использовать аббревиатуру «Неопределённое Поведение» или «НП»?

      А по поводу отступов, чисто вот сам сталкивался, если текст набираешь в ворде, то потом он копирует без отсупов. Обычно держу отдельный тектовичок для кода. Просто потом при вёрстке лениво доправлять бывает. Буквально со своей последней трилогией так накололся.


      1. Asiman
        14.06.2022 17:44
        +19

        Это незнакомая аббревиатура, которая заставляет искать перевод термина и помнить его значение на протяжении всей статьи.

        UB - является устоявшимся термином и его перевод на русский является скорее нежелательным


  1. edo1h
    14.06.2022 13:07
    +11

    Преимущества Rust не ограничиваются безопасным доступом к памяти, есть ряд других полезных свойств, которые могли бы облегчить труд разработчиков ядра Linux. Взять хотя бы инструментарий для управления зависимостями. Много-ли тех, кому по душе сражаться с include путями в заголовочных файлах, раз за разом запускать pkg-config вручную, либо через макросы Autotools, полагаться на то, что пользователь установит нужные версии библиотек?

    эээ… как говорится, где ядро linux, и где autotools?


  1. dlinyj
    14.06.2022 14:14
    +1

    Недостатки си достаточно очевидны. Как по мне, лучше будет доработать компилятор и добавить опцию, которая бы отлавливала такие моменты неопределённого поведения, чем внедрять дополнительный язык.
    Лично для меня внедрение нового языка, тут же превратит элегантный код ядра в мурзилку.


    1. unC0Rr
      14.06.2022 15:04
      +12

      Но вы же понимаете, что в результате «доработки компилятора» получится новый, совершенно другой язык программирования?


      1. Alpha_Ceph
        14.06.2022 15:41
        +13

        Clang делает тучу проверок, никак не прописанных в стандарте языка: например, кидает ворнинг на присваивание вида

        if (a = b) /*...*/ ;

        Предупреждение глушится парой дополнительных скобок:

        if ((a = b)) /*...*/ ;

        Мне не кажется, что из-за подобных проверок Clang перестаёт быть компилятором C.


      1. dlinyj
        14.06.2022 16:16
        +1

        К сожалению нет, потому что можно просто добавить дополнительную опцию компиляции, добавляющую этот функционал. И есть ряд компиляторов, которые намного строже следят за таким, запрещая неоднозначности (программировать с ними одно неудовольствие).


    1. Sin2x
      14.06.2022 18:19

      Есть такие вещи, как MISRA C и Checked C, которые устраняют большинство проблем:

      https://en.wikipedia.org/wiki/MISRA_C

      https://github.com/microsoft/checkedc


      1. JustForFun88
        14.06.2022 21:34
        +2

        Но они никак не помогают при написании асинхронного кода


        1. Sin2x
          14.06.2022 22:47
          -1

          1. vabka
            15.06.2022 03:20
            +1

            В Си надо читать мануал:

            Смысл Rust как раз в том, что конечному разработчику не нужно читать мануал — благодаря типам, тебе компилятор просто не даст сделать что-то неправильное.
            И при этом всё будет легко читаться.

            Много думать нужно только в ситуации, когда ты сам собираешься написать свой асинхронный рантайм.

            Ну а C++ в ядре нет и не будет.


            1. Sin2x
              15.06.2022 06:55
              +2

              В Расте есть точно такой же ансейф код, и уж точно он не является никакой волшебной кнопкой, которая сделает тебе всё хорошо, даже если ты не прочитал ман. RTFM всегда RTFM. В системном программировании не бывает серебряных пуль.

              У меня складывается впечатление из комментариев под каждым постом про раст, что это какая-то секта и религия, настолько всё восторженно и однотипно.


              1. Cerberuser
                15.06.2022 08:39
                +4

                Фишка в том, что в C мануалы надо читать всем, а в Rust - только тем, кто пишет unsafe. Так-то да, безусловно, вообще без них не бывает, вопрос лишь в количестве.


                1. edo1h
                  15.06.2022 08:54
                  +1

                  вы явно кривите душой. не читая мануалов я сейчас даже hello world на rust'е не напишу.


                  1. 0xd34df00d
                    15.06.2022 08:56
                    +4

                    Разница в том, что в расте их надо прочитать один раз, а в сях — постоянно (хотя и менее постоянно, чем в плюсах).


                    1. edo1h
                      15.06.2022 09:27

                      хм, а зачем постоянно читать мануалы по си?


                      1. 0xd34df00d
                        15.06.2022 09:28
                        +5

                        Чтобы убедиться, что в данной конкретной строчке нет UB.


                      1. edo1h
                        15.06.2022 09:46
                        +1

                        вы явно преувеличиваете. если не брать библиотечные функции, то ub не так уж много, и у всех понятно откуда ноги растут, если воспринимать си как переносимый ассемблер, то они неожиданностью не являются.


                      1. 0xd34df00d
                        15.06.2022 18:02
                        +4

                        Неа, не преувеличиваю, а сужу по собственному опыту (с плюсами, и, конечно, убирая плюсовую специфику — скажем, проблем с лайфтаймами в C нет).


                  1. Cerberuser
                    15.06.2022 09:14
                    +2

                    Мануалы по Rust - естественно, нужны, как и с абсолютно любым другим языком (там, где они не нужны для написания кода, они становятся нужны, когда - не "если" - этот код ломается; JavaScript тому живым примером). Вопрос был изначально, насколько я понял, не об этом, а о том, чтобы знать детально все правила по безопасной работе с нижележащими компонентами, которые в C должны быть учтены на всех уровнях, а в Rust, если их учесть на нижнем уровне, выше они будут выражены в виде проверяемых компилятором ограничений.


                1. Sin2x
                  15.06.2022 09:26
                  -2

                  Как ты собрался писать ядро ОС без Unsafe? Этот пост про линукс кернел.

                  Если не хочешь читать мануалы, пиши на интерпретируемых языках. Хотя рано или поздно и там придётся погружаться в подсахарные горы.


                1. mikhanoid
                  15.06.2022 10:41

                  Так это поэтому для Rust нет нормальных мануалов по структурам данных? Потому что они все требуют unsafe?


              1. 0xd34df00d
                15.06.2022 08:48
                +2

                настолько всё восторженно и однотипно.

                Не, ну почему. Я вот не люблю раст, но С я не люблю ещё больше.


      1. 0xd34df00d
        15.06.2022 08:47
        +4

        Которыми почему-то не особо пользуются на практике, если на то нет регуляторных требований, и которые проблемы в логике не устраняют и даже не помогают устранить.


        1. Sin2x
          15.06.2022 10:21

          Мне даже интересно стало -- а как, собственно, Раст (да и вообще любой язык программирования) может устранять проблемы в логике программы? Или помочь их устранить?


          1. mikhanoid
            15.06.2022 11:07
            -5

            В статье примеры проблем перечислены. Большинство искусственные, конечно. Но когда это останавливало разработчиков новых прекрасных языков программирования? За Linux вот только страшновато. Обычно софт на Rust выходит корявым логикой своей работы, потому что Rust уж слишком ограничивает выразительные возможности.


            1. unC0Rr
              15.06.2022 11:19
              +2

              Ограничивает выразительные возможности? Любопытно было бы взглянуть на пример того, как вы это понимаете.


              1. mikhanoid
                15.06.2022 12:07
                -2

                Мой любимый пример - реализация двусвязного списка на Rust. Даже на Haskell это проще сделать.


                1. Cerberuser
                  15.06.2022 13:41
                  +1

                  Ну, допустим, вы его реализуете. А зачем? В какой практической задаче он будет значимо эффективнее обычного вектора?


                  1. DirectoriX
                    15.06.2022 14:07
                    +2

                    … а даже если будет — есть готовый двусвязный список в виде std::collections::LinkedList


                    1. mikhanoid
                      15.06.2022 16:11
                      -1

                      И чем это лучше реализации на Си? Unsafe-код есть, ручное управление памятью есть, потокобезопасности нет. ????????‍♂️


                      1. Cerberuser
                        15.06.2022 16:26
                        -1

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


                      1. DirectoriX
                        15.06.2022 16:35
                        +4

                        И чем это лучше реализации на Си?
                        Хотя бы тем, что это в стандартной библиотеек языка, готовое, протестированное, даже с некоторыми гарантиями (ведь rustc проверяет и unsafe блоки). Встречный вопрос: чем это хуже реализации на Си (кроме потенциального «это написано мной, поэтому оно лучше по определению»)?
                        Потокобезопасность — вообще не связанное со списками понятие, даже обычные int / i32 — не потокобезопасные. Кстати, Rust не даст вам предать потоко-опасные (без реализации трейта Sync) переменные в соседний тред, всё завершится ошибкой сборки, если нужна многопоточность — оборачивайте в Arc<Mutex<>> или что-то аналогичное. А что там в C?


                      1. mikhanoid
                        15.06.2022 17:14
                        -5

                        Система типов в Rust - unsound, и допускает ошибки, а сам проверяльщик с багами. Поэтому эти проверки 100% гарантий не дают.

                        Про библиотеку не понятно. Мы же говорим о программировании в Linux, так ведь? В ядре есть библиотека примитивов. Она тоже протестирована, гораздо лучше, кстати, чем Rust, и тоже даёт гарантии.

                        Си лучше тем, что он не даёт ложных обещаний корректности программисту, и программист думает, когда пишет код, отлаживает и тестирует экзотические и паталогические поведения.

                        В Rust программист борется с системой типов, обычно, полагаясь на неё. Н,о на самом деле, гарантий никаких нет. Вы загрузили два драйвера в ядро, что будет гарантировать, что они не используют одну и ту же очередь, без Sync? Как компилятор это проверит? Кроме того, при тестировании нельзя создать паталогические сценарии, потому что система типов и структуру тестов ограничивает - снова нужен unsafe или ffi (unsafe в тестах, Карл!)

                        Что делать с обработчиками прерываний? И т.д. и т.п. Вопросов много, а ответ один: unsafe. Ну и зачем такое счастье?

                        Вот, например, понятно, зачем вкорячивать Lua в ядро NetBSD: дополнительная гибкость и скорость разработки. Зачем вкорячивать Rust в Linux - я не понимаю. Это только повысит трудоёмкость разработки, но ничего не даст взамен (везде будет unsafe из-за специфики ядер операционных систем).


                      1. 0xd34df00d
                        15.06.2022 18:08
                        +3

                        Система типов в Rust — unsound, и допускает ошибки, а сам проверяльщик с багами. Поэтому эти проверки 100% гарантий не дают.

                        Да, 100% гарантий не дают, но даже это лучше, чем ничего.


                        MISRA C тоже 100% гарантий не даёт, и что из этого следует?


                      1. mikhanoid
                        15.06.2022 21:01
                        -3

                        Это хуже, потому что там бывают весьма серьёзные протечки: из стека в static, например. В Си вы знаете, что так может быть, и следите за этим, структурируете программу соответствующим образом. В Rust вы верите, что так не бывает, и не следите, а потом долго удивляетесь, что вам сносит стек. При этом, опасное поведение может быть запрятано в библиотеке.

                        Rust даёт обещания, которые не выполняет, и полагаться на него нельзя. Всё равно, приходится прогонять всё через valgrind какой-нибудь. Так зачем тогда Rust?


                      1. 0xd34df00d
                        15.06.2022 21:43
                        +1

                        А, ну это уже хорошие вопросы, это надо растоманов спрашивать.


                        Правда, эти вопросы не являются ответом на мой исходный вопрос. На расте статик там куда-то протечёт, а на С даже с мизрой я не смогу построить замкнутую систему единиц измерений. Что из этого хуже — большой вопрос.


                      1. Cerberuser
                        16.06.2022 06:22

                        Для ядра - однозначно первое, потому что замкнутая система единиц измерений там всё равно будет никому не нужна ещё лет сто.


                      1. 0xd34df00d
                        16.06.2022 19:29
                        +2

                        А вот то, что дают типы для какого-нибудь компилятора, учитывая наличие eBPF, нужно уже вчера.


                      1. deadfish45
                        16.06.2022 22:31

                        обычные int / i32 — не потокобезопасные. Кстати, Rust не даст вам предать потоко-опасные (без реализации трейта
                        Sync) переменные в соседний тред, всё завершится ошибкой сборки, если
                        нужна многопоточность — оборачивайте в Arc<Mutex<>> или
                        что-то аналогичное. А что там в C?

                        В С есть cmpxchg.h

                        Не знаю как в расте, всё руки не доходят посмотреть на него, действительно ли он не даст передать потоконебезопасные, обычные i32 в соседний тред, и как концепция тредов будет работать в ядрёном контексте, где тред-то по сути один, а критическую секцию создают асинхронные события или обработчики, например, прерываний. Но лучше бы давал, потому что синхронизация через cmpxchg помогает с быстродействием. М.б. уточнение про трейт Sync это схожая конструкция.


                  1. mikhanoid
                    15.06.2022 16:04
                    -1

                    В ядре операционки. На уровне приложений вам эффективное изменение размера вектора обеспечивает виртуальная память - remap всякий. В ядре такой роскоши нет, а необходимость поддерживать fifo порядки есть. На самом деле, нужны более сложные структуры данных с переменным количеством элементов. Но если в Rust даже простая очередь - это небольшой unsafe адок, то что говорить о более сложных конструкциях?


            1. Sin2x
              15.06.2022 12:07
              -2

              То, что я увидел в статье, должно отслеживаться статическими анализаторами кода, как тот же PVS Studio. Изобретение нового языка для этого не требуется.


              1. dlinyj
                15.06.2022 14:38
                -2

                Интересно, кто так бегает и люто минусит совершенно нейтральные комментарии.


                1. 0xd34df00d
                  15.06.2022 18:14
                  +2

                  Во-первых, это нейтральный эмоционально, но не нейтральный с точки зрения корректности комментарий: он фактологически и технически неверен. Мы стали забывать, но хабр когда-то начинался как социалочка для технических обсуждений, поэтому подобная верность тоже важна (и, я бы сказал, важнее эмоций).


                  Во-вторых, не могу не отметить забавный выбор слов в вашем комментарии — «бегает и люто минусит», учитывая, что вы бегаете по комментам и ноете про плюсики-минусики :]


                  1. dlinyj
                    15.06.2022 18:32

                    В данном случае человек спокойно написал, меня удивляет что прям кто-то прошёлся и в порыве гнева сливает его комментарии, явно следит за этим. Ну я заступился за него.

                    учитывая, что вы бегаете по комментам и ноете про плюсики-минусики :]

                    А я-то тут при чём? Вы безосновательно обвиняете меня в том, чего нет. Прошу извинится за свои слова, можете просмотреть все комментарии мои за пол года.


                    1. 0xd34df00d
                      15.06.2022 18:39
                      +1

                      меня удивляет что прям кто-то прошёлся и в порыве гнева сливает его комментарии, явно следит за этим.

                      В комментарии выше -3, у значимой части комментариев больше одного минуса, так что откуда вы знаете, кто и как за ним следит, и сколько их? Откуда вы знаете про порыв гнева? Зачем вы выстраиваете именно такой фрейминг какого-то баттхёртнутого неадеквата, который бегает и минусует комментарии?


                      А я-то тут при чём? Вы безосновательно обвиняете меня в том, чего нет.

                      Это рекурсивный намёк на важность выбора слов.


                      Впрочем, учитывая сказанное выше вами, по комментариям вы бегаете (просто по чужим — проверяете, сколько там плюсов и минусов), и про плюсики-минусики ноете, так что я утверждаю, что фактологически мой комментарий верен.


                      1. dlinyj
                        15.06.2022 18:42

                        Переход на личности (argumentum ad hominem) — распространённый в Интернете (в частности, в Википедии) демагогический приём, подразумевающий дискредитацию аргументации оппонента посредством дискредитации его и/или его действий, а также провоцирующий некорректную ответную реакцию оппонента (в этом смысле переход на личности является формой троллинга).


                        Стыдно, товарищ, стыдно. Безосновательные обвинения.


                      1. 0xd34df00d
                        15.06.2022 18:54

                        Ещё раз, давайте посмотрим, что делаете вы, причём, наполовину — вне всякого контекста обсуждений плюсиков, минусиков и неадекватов. Вы пишете:


                        1. про существование минимум одного человека, который ставит свой целью ставить минусы («кто так бегает»),
                        2. с негативными коннотациями суетливости, необдуманности решений («бегает»),
                        3. с их усилением («люто»),
                        4. про эмоции нашего гипотетического лютого бегуна («в порыве гнева»),
                        5. про неадекватное поведение («явно следит за этим» — а следить за оценками комментариев как-то странно).

                        …но на личности, оказывается, перехожу я. Ну ок.


                      1. dlinyj
                        15.06.2022 19:18

                        Мне жаль что мы скатываемся в токичную дискуссию.
                        Мне не хочется ссорится с вами, скатываясь в переброску обвинений (которые бессмысленны). Конкретно в данном случае, мне показалось что автора комментария безосновательно минусят, и допускаю, что эпитеты которые я подобрал были не очень корректными.

                        Но, мне правда неприятно, что вы оговариваете меня в том, чего реально нет. Давайте не будем разводить токсичность на данном ресурсе, мы в одной лодке.


          1. 0xd34df00d
            15.06.2022 18:07
            +2

            а как, собственно, Раст (да и вообще любой язык программирования) может устранять проблемы в логике программы?

            Выражая больше инвариантов на уровне типов. Начиная от каких-нибудь размерностей вроде всяких квадратных метров в наносекунду (с чем справится и раст, и даже C++), и заканчивая доказательством того, что ваша условная функция сортировки действительно сортирует (для чего, впрочем, даже хаскеля недостаточно).


            1. Sin2x
              15.06.2022 18:10

              Тогда мне, пожалуй, стоит переформулировать на "а как, собственно, Раст (да и вообще любой язык программирования) может устранять ошибки в логике программы?"


              1. 0xd34df00d
                15.06.2022 18:16
                +3

                Устранять — не может, а вот гарантировать, что некоторый класс ошибок просто не возникнет в программе, если она скомпилируется — может. Просто типы не сойдутся.


                Устранять их, конечно, всё равно придётся программисту, язык тут только выявлять их помогает.


                1. Sin2x
                  15.06.2022 18:29

                  Ошибки в логике это ошибки в алгоритмике, и никакой язык их не устранит, потому что язык просто делает то, что ему говорят. Я об этом.


                  1. 0xd34df00d
                    15.06.2022 18:32
                    +3

                    Если вы в типе написали, что ваша функция сортирует, то вам придётся сортировать, и никуда тут не деться.


                    1. mikhanoid
                      15.06.2022 21:04

                      Только сортировать она сможет лишь списки, и лишь одним медленным способом.


                      1. 0xd34df00d
                        15.06.2022 21:42
                        +2

                        Почему это?


                      1. mikhanoid
                        15.06.2022 21:45

                        А где можно посмотреть доказательство корректности битонной сортировки, например?


                      1. 0xd34df00d
                        15.06.2022 22:23
                        +1

                        Не очень распространённый алгоритм, мало кому нужно его доказывать, видимо, но можно здесь (если утырите pdf'ку — скиньте почитать, самому интересно, как 20 лет назад вещи доказывали, а на сцилабе меня забанили).


            1. cepera_ang
              15.06.2022 18:16
              +4

              И ещё немного навязываемой культурой. Если в одной языке не только вычеркнуты целые классы ошибок, но ещё и просто принято среди разработчиков и удобно реализовано бороться с другими, то в проектах написанных на этом языке будет в среднем меньше ошибок, чем в проектах на языках, в которых принято относиться по принципу «и так сойдет».


              В тот же Rust идут те, кто изначально настроен писать более безопасные программы, это одна из продающих фишек языка (иначе зачем «мучаться» с изучением?) и вокруг языка есть культура более тщательной разработки, обмазывания тестами, фаззерами и бенчмарками. В отличие от того же С или плюсов, где культура скорее «все баги вносит программист, а значит сделать всё равно ничего невозможно, если бы могли писать лучше — написали бы сразу лучше».


              1. mikhanoid
                15.06.2022 21:49
                -2

                Да ладно? Проекты на Си обмазывают тестами, фаззерами, разнообразными статическими анализаторами весьма обильно. Инструментов для этого предостаточно.


                1. cepera_ang
                  15.06.2022 21:59
                  +3

                  Как думаете, сколько штук из 100 случайных проектов на С будет использовать статический анализ и хоть какой-нибудь фаззер?


                  1. mikhanoid
                    15.06.2022 22:21
                    -1

                    Не знаю. Но прелесть в том, что это можно сделать независимо от авторов проекта. Если нужно, вы берёте, например, libpng, дописываете спецификации какого-нибудь Farma-C, и проверяете. И для этого не нужно ограничивать выразительность исходного языка.


                    1. cepera_ang
                      15.06.2022 22:26
                      +4

                      Берёте libpng, обмазываете анализаторами, находите гору багов, и… дальше что? Какая стратегия? Вываливаете их на авторов, которые с превеликим удовольствием начнут править все эти непонятные вылеты? Или быстренько правите сами.


                      А потом повторяете по всем десяткам тысяч сишных либ на вашем компьютере?


                      А потом всё равно CVE… CVE… CVE…


                      1. mikhanoid
                        15.06.2022 23:32
                        -1

                        А что делать? Ждать, когда эти десятки тысяч либ перепишут на Rust? Так, ведь, никогда не перепишут. Проблема Rust в том, что он просто не позволяет реализовывать некоторые алгоритмы в safe-режиме. А менять unsafe C на unsafe Rust не особо экономически оправдано. Поэтому, да, проще взять и проверить критически важные библиотеки на C. Собственно, все так и делают, кому безопасность важна.


                      1. cepera_ang
                        15.06.2022 23:36
                        +1

                        Как минимум не начинать новые проекты на С. А дальше посмотрим — что-то потихоньку переписывается (у многих компаний есть NIH-синдром и «переписать на rust/go/zig» тут отлично подходит), что-то тянут на сях, такова жизнь.


                      1. mikhanoid
                        15.06.2022 23:44

                        Да, да, конечно. Именно NIH-синдром. И у каждой компании собственный компилятор Си... Не поэтому людям Rust не заходит, совсем не поэтому. Ещё раз повторю: нельзя на safe Rust закодировать некоторые алгоритмы. А дальше вопрос: зачем на Rust переходить, если будет, всё равно, unsafe? Просто, потому что модно, что ли?


                      1. cepera_ang
                        16.06.2022 00:09
                        +5

                        unsafe Rust всего лишь чуть лучше normal C. Если 1% (или даже 5 или 25) кода будет unsafe — это всего лишь значит, что подавляющая часть кода будет safe, а остальная — не хуже, чем было.


                        А на практике, оказывается, что unsafe преимущественно используется для вызова тех же самых сишных библиотек и изредка, чтобы указателями поиграть в блоке на три строчки.


                      1. mikhanoid
                        16.06.2022 10:29
                        -3

                        Не правда. На практике unsafe используется даже в коде тестов, потому что без unsafe не триггернуть некоторые поведения. И смотреть надо не на то, сколько по объёму этот unsafe занимает, а на какой код он влияет, и там уже будет точно не 1%. В Rust могут быть крайне мозголомные утечки даже без unsafe, а с unsafe можно нарушать любые гарантии.

                        В Си, мы знаем, что можем снести себе ногу, и работаем осторожно, структурируем программы так, чтобы минимизировать риски. В Rust вы можете просто не знать об ошибке: компилятор съел код, и точка, вы верите, что всё хорошо. Народ, ведь, именно так и программирует: не через дизайн системы, а через затыкание компилятора. Смотрите на кучу unwarp повсеместно во всём коде на Rust. Это существенно снижает качество ПО, а не повышает.


                      1. cepera_ang
                        16.06.2022 11:15
                        +5

                        В Си, мы знаем, что можем снести себе ногу, и работаем осторожно, структурируем программы так, чтобы минимизировать риски.

                        Это самый смешной анекдот, который я видел за последнее время.


                      1. mikhanoid
                        16.06.2022 12:07
                        -1

                        Смешной анекдот - это реализация Redox.


                      1. repeat
                        16.06.2022 21:29
                        +1

                        Не язык виноват, что на нём пишет криворукий. Безопасность прежде всего должна обеспечиваться тем, кто пишет код. Компилятор и тулзы это уже вторично. Как бы не получилось так, что Rust продвинет тему безопасного кода, где первичен компилятор.


                      1. DirectoriX
                        16.06.2022 22:41

                        Тогда можно и правила дорожного движения (возня с borrow checker и типами) отменить: вроде бы большинство их соблюдает, но некоторые нет (unsafe), иногда неумышленно (тормоза отказали или ещё чего; баги компилятора). А если все будут думать головой (писать без ошибок) и смотреть по сторонам (делать все нужные проверки) — тогда и без правил (проверок компилятора) не будет аварий (крашей, порчи данных и т.д.).


                      1. repeat
                        17.06.2022 08:40

                        вы неверно истолковали мой посыл. исключать "правила дорожного движения" нельзя. они должны подстраховывать, но не стать страховкой

                        при наличии этих правил, неумеющий ездить и полагающийся только на инструктора, не лучший участник движения.


                      1. DirectoriX
                        17.06.2022 09:45

                        Пусть лучше неумеющий ездить, но соблюдающий правила, чем опытный водила, который чихал на эти ваши светофоры, знаки и ограничения скорости.
                        Первый, может, медленнее и неуклюже, зато хоть точно доедет, а вот второй может приехать в могилу (иногда и не один).


                      1. mikhanoid
                        17.06.2022 09:54

                        Если бы все ездили только по правилам, аварийность была бы гораздо выше. Иногда приходится совершать запрещённые манёвры, чтобы избегать столкновений. В крупных городах приходится делать это довольно часто.

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

                        Кроме того, аналогия плохая. Правила - для людей, а не для машин. Это как code style, а не как borrow checker. И правила довольно часто пересматривают, чтобы адаптироваться к новым реалиям. Про borrow checker такого не скажешь, адаптивностью он не отличается.


                      1. cepera_ang
                        17.06.2022 07:37
                        +1

                        Не язык виноват, что на нём пишет криворукий. Безопасность прежде всего должна обеспечиваться тем, кто пишет код.

                        Если почитаете литературу про безопасность (safety) систем в реальном, физическом мире, то обнаружите, что человек считается там слабым звеном — люди отвлекаются, ошибаются, бывают недостаточно обучены и т.д. Но при этом никто не применяет подход «люди ошибаются, ну и ладно, значит такова судьба», нет. Вместо этого все возможные способы — кнопки делаются разного цвета и размера, закрываются от случайных нажатий, регулируется перегрузка индикаторами, дублируются функции и внедряются контрольные списки и двойные проверки и ещё миллион вещей, культура безопасности. Не «сам дурак, что ходил в куртке и затянуло в станок за рукав», а «как так получилось, что ходил в куртке и никто не обратил внимания и не заставил переодеться?». Эшелонированная защита.


                        Вот и в программировании так же: люди рассортировываются сами по предпочтениям. В сторону раста тянутся те, кто понимает, что возможности программиста ограничены, за всем не уследишь, особенно если будешь пытаться следить за всеми мелкими вещами, которые позволяет сделать условный С. Эти люди верят в то, что можно и нужно полагаться на инструменты для устранения части проблем и сосредотачиваться на своей, сложной логической части.


                        В С же идут (или остаются) либо те, кто понимает ограничения инструмента, но вынужден им пользоваться, либо самоуверенные ковбои, которым не нужна никакая помощь от системы, они никогда не отвлекаются и не ошибаются.


                        Поэтому совершенно непонятно, как более безопасный в плане и тулинга и отношения Rust может продвинуть какую-то плохую тему.


                      1. repeat
                        17.06.2022 08:29

                        Все правильно написали. Замечу лишь, переход на раст с другого языка для повышения безопасности видится правильным решением. Вхождение через раст в программирование, расхолаживает и привьет плохой подход. Зачем думать о безопасности, подскажет ведь в случае чего.


                      1. cepera_ang
                        17.06.2022 08:50

                        По такой логике множество других языков расхолаживают и прививают ещё более плохой подход. Что тогда говорить про условный питон, который даже не упоминает о том, что есть какая-то память, которой нужно управлять? Который интерпретируется и работает по дефолту раз в сто медленнее? И в котором можно передавать строку в функцию, которая ждёт числа и узнаешь только когда упадёт в работе.


                        Нужно ли страдать в расте с его борроу-чекерами, возиться с типами и обязательной обработкой всех ошибок (пусть даже только unwrap’ом), если можно всё это игнорировать вообще (как и делается в 90% языков)? Те, кто останутся в расте отвечают на этот вопрос положительно, значит видят ценность в дополнительных гарантиях языка. Можно ли назвать это расхолаживанием? Выглядит наоборот как излишняя дисциплина.


                      1. repeat
                        17.06.2022 08:59

                        кто начал с раста, придя в питон, сломается. ведь теперь надо думать, чтоб не передать строку в функцию с числом


                      1. mikhanoid
                        17.06.2022 09:55

                        Я пришёл в Python после Haskell. Ничего не сломалось, в безумную обезьяну, которая пытается передать строки вместо чисел я не превратился. Что я делал не так?


                      1. mikhanoid
                        17.06.2022 09:42

                        Кроме Rust есть множество безопасных языков программирования, которые позволяют работать со сложными структурами данных без необходимости пересекать границу unsafe. Тем, кому нужна безопасность, идут в эти языки, и пишут большую часть кода на них, оставляя только небольшие чувствительные к производительности участки для реализации на языках с более слабыми гарантиями безопасности. Но это небольшие участки кода, нет никакого смысла использовать для них такой громоздкий язык, как Rust, в котором они были бы, всё равно, реализованы unsafe.


                      1. AnthonyMikh
                        16.06.2022 13:26
                        +1

                        На практике unsafe используется даже в коде тестов, потому что без unsafe не триггернуть некоторые поведения.

                        А можно, пожалуйста, предъявить доказательства этому заявлению? А то звучит, как наглый пиз наглая намеренная ложь.


                      1. DirectoriX
                        15.06.2022 23:56
                        +4

                        он просто не позволяет реализовывать некоторые алгоритмы в safe-режиме
                        Сильное заявление. Мне даже интересно, почему (на ваш взгляд):
                        1. эти некоторые алгоритмы не являются вычислимыми
                        2. safe-подмножество Rust не является полным по Тьюрингу
                        Если первое — тогда вообще никакой язык не поможет, если второе — хочется увидеть доказательство. Спойлер: его не будет, потому что, например, вот реализация Тьюринг-полной «Жизни».

                        safe-подмножество Rust не позволяет «красиво» реализовывать некоторые алгоритмы — возможно, но встаёт другой вопрос: что такое «красиво», как это померить, как сравнить с другими языками? И как быть с примерами, когда на safe Rust какой-то алгоритм реализовали «красивее», чем на том же С?


                      1. mikhanoid
                        16.06.2022 00:03

                        Ещё раз повторю свой вопрос: покажите safe-реализацию очереди на Rust. Вопрос не об абстрактной полноте, а о совершенно конкретных алгоритмах и структурах данных.

                        Я, конечно, понимаю, что теоретикам от терий типов безразлично, будет очередь O(1) или O(n), но на практике, особенно при программировании ядра OS, это чертовски важно


                      1. 0xd34df00d
                        16.06.2022 02:11
                        +1

                        Я, конечно, понимаю, что теоретикам от терий типов безразлично, будет очередь O(1) или O(n)

                        Ну вообще-то важно.


                      1. mikhanoid
                        16.06.2022 12:47
                        -2

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

                        И это, в принципе, ok. Это имеет право на существование. Это интересно. Если бы не эта вся агрессивная pr-компания по пропихиванию Rust во все места... Довели бы до ума Redox, написали бы manual: классические алгоритмы и структуры данных на Rust - было бы хорошо, люди бы потянулись. Может быть, надо сначала научиться нормально, не через хэши, кучу Фибонначи реализовывать, и только потом уже в ядро лезть?

                        Но, ведь, нет. Нам втирают без каких либо достоверных обоснований, что это better C. Но по исходникам Redox и Servo видно, насколько better: Rust - очередная итерация "the worse the better".


                      1. Mavolio-Bent
                        16.06.2022 09:54

                        Вы говорите об аналоге обычной std::queue? Тогда что-то вида

                        struct Node<T> {
                        	data: T
                          next: Refcell<Rc<Node<T>>>
                          parent: Refcell<Weak<Node<T>>>
                        }
                        
                        struct Queue<T> {
                        	Option<Node<T>> head;
                        }

                        Правда, тут будет O(n) front(), чтобы сделать константным, наверное, надо делать
                        Option<Refcell<Node<T>>> head
                        Option<Refcell<Node<T>>> tail;


                      1. mikhanoid
                        16.06.2022 10:30

                        А реализация операций? С нетерпением жду.


                      1. DirectoriX
                        16.06.2022 13:38

                        Да что ж такое-то, привязались к своим спискам и не можете в поисковик вбить «rust linked list» и ткнуть по второй ссылке (при том что первая — документация std::collections::LinkedList).
                        Вот, держите: ссылка на полный код. Там есть тесты, которые успешно выполняются.


                      1. mikhanoid
                        16.06.2022 13:53

                        Да что же любители Rust такие поверхностные-то? Там прямым текстом в коде написано, что нельзя пройти по списку без его разрушения. Нельзя взять элемент из середины. Да и читал я этот блог, когда пытался что-нибудь более или менее работоспособное на Rust написать.


                      1. cepera_ang
                        16.06.2022 13:54
                        +2

                        Но это сложный код! Случайных прохожий такой с нуля не напишет! Следовательно Rust хуже чем С, в котором любой должен накидывать свои кривенькие структуры данных, потому что в стандартной библиотеке шаром покати, а о том, чтобы существовали общепринятые сторонние библиотеки с лёгкой интеграцией — вообще неслыхано.


                      1. mikhanoid
                        16.06.2022 14:00
                        -1

                        Да, он сложный. Это сложный код, который не решает тривиальную задачу. В операционке гораздо гораздо всё сложнее со структурами данных. Соответственно, код будет распухать, скорость разработки будет падать, функциональность будет страдать. Производиельность тоже, потому что это всё нифига не бесплатно. Можете сравнить ассемблер реализации на Rust и аналогичной реализации на Си. Не, конечно, если цель сделать разработку Linux более дорогой и недоступной широкому кругу любителей, а сам код более ресурсоёмким, то верной дорогой идёте, товарищи! Только вот будет ли такой Linux Linux-ом? Надеюсь, будет создан какой-нибудь stainless fork.


                      1. cepera_ang
                        16.06.2022 14:42

                        Можете сравнить ассемблер реализации на Rust и аналогичной реализации на Си.

                        Раз это такой важный аргумент для Сишников, то они уже сто раз сравнили и обосновали все ваши «всё сильно-сильно хуже» в цифрах и конкретных данных? И вы кинете где это готовое почитать?



                      1. 0xd34df00d
                        16.06.2022 19:27
                        +1

                        Производиельность тоже, потому что это всё нифига не бесплатно.

                        «Нифига не бесплатно» — это на самом деле алиасинг или войд-звёздочка, через которую компилятор ничего не может видеть.


                        С — довольно паршивый язык для написания действительно производительного кода.


                      1. mikhanoid
                        16.06.2022 19:59

                        Компиляторы давно умеют анализировать псевдонимы, и хорошо их видят. Кроме того, есть restrict, если компилятору нет доверия.

                        Не очень понятно, откуда в рассуждениях взялся void со звёздочкой.


                      1. 0xd34df00d
                        16.06.2022 22:12

                        Компиляторы давно умеют анализировать псевдонимы, и хорошо их видят.

                        Практика показывает, что нет.


                        Не очень понятно, откуда в рассуждениях взялся void со звёздочкой.

                        Из любого более-менее обобщённого алгоритма или структуры данных.


                      1. mikhanoid
                        17.06.2022 09:25

                        Какая практика? Можно подробнее?

                        В экосистеме C, если и делают обобщённые структуры данных, то не через void*, а через макросы -- жаба же давит указатель лишний раз разыменовывать. Но такая потребность возникает редко, потому что на Си обычно пишут узкоспециализированные утилиты и библиотеки, в которых нет особого простора для обобщений.


                1. 0xd34df00d
                  15.06.2022 22:20
                  +2

                  А дырки всё равно находятся.


  1. wyfinger
    14.06.2022 14:50
    +1

    Когда для rust появится хотябы вторая реализация компилятора?


    1. Browning
      14.06.2022 15:38
      +8

      (оставляя в стороне вопрос зачем) Теоретически -- вот: https://github.com/thepowersgang/mrustc


    1. torgeek
      14.06.2022 16:05
      +5

      Есть такое https://github.com/Rust-GCC


  1. Sin2x
    14.06.2022 17:13
    -5

    1. vabka
      15.06.2022 03:38
      +7

      Я попробую чуть более подробно развернуть каждый пункт.
      Как минимум, топик написан 3 года назад, и некоторые моменты не актуальны.

      C is the most portable programming language.

      Rust портативен ровно на столько, на сколько портативен LLVM (а в будущем и GCC, если rust-gcc станет стабильным)
      В принципе для разработки драйверов для ядра Linux совершенно не обязательно поддерживать абсолютно все архитектуры, какие существуют в природе.

      C has a spec

      Компилятор и тесты на обратную совместимость — наиболее полная спецификация.
      Цена спецификации нулевая, если разные реализации привносят свои уникальные фичи, или не полностью реализуют фичи из спецификации.

      В целом сообщество признаёт эту проблему и когда-нибудь полноценная спецификация будет, но сейчас есть более приоритетные задачи.
      C has many implementations

      Rust-GCC. В целом «много конкурирующих реализаций» не могут быть преимуществом сами по себе.
      Есть целая куча активно используемых ЯП, которые не имеют альтернативных реализаций.
      Ну и Linux, на сколько я помню, не предполагает работу с десятками разных компиляторов.

      C has a consistent & stable ABI

      Эта проблема официально признана, но пока язык активно развивается — стабильный ABI это развитие остановит.
      Если нужен стабильный ABI — всегда можно сделать extern «C» или использовать какой-нибудь другой ABI (wasi например)
      Ну и разработке драйверов это не мешает.

      Cargo is mandatory

      Нет, cargo не обязателен, хоть и не рекомендуется работать без него (лично я не вижу ни одной причины отказываться от cargo).
      В целом никто не запрещает использовать rustc и строить свою экосистему пакетов и инструментов.
      Ну и это также не является больной проблемой ни для разработки ядра, ни для Embedded.

      Concurrency is generally a bad thing.

      «У каждого инструмента есть свои особенности, и свои задачи».
      Вроде у нас сейчас 2022 год, а значит в компьютерах у нас многоядерные процессоры. А значит, если мы хотим сделать что-то, что будет эффективно использовать все имеющиеся ресурсы — придётся всё равно уйти в конкурентность. Не важно в каком виде.

      Rust не обязывает писать конкурентный код, и защищает твои ноги, если вдруг тебе нужно будет работать с общим состоянием.
      Си не запрещает писать конкурентный код, и не даёт тебе никаких инструментов для защиты.

      Ну и тут автор просто делает реверанс в сторону Go и его горутин и каналов, думая что это не конкурентный код.

      Ну и да. Ядро Linux одна из таких программ, которая не может обойтись без параллельного или конкурентного программирования.

      Safety.

      Тут автор вообще говорит «я не тупой, я сам могу всё учесть, чтобы не получить segfault».
      Так что аргумент не аргумент.


      1. Sin2x
        15.06.2022 08:22
        +1

        Фундаментальная суть проблемы раста описана там в последнем параграфе. И изменить её невозможно ни за пять, ни за 10 лет, потому что это сама философия языка. Тут потребуется написать другой язык.

        C is far from the perfect language - it has many flaws. However, its replacement will be simpler - not more complex. Consider Go, which has had a lot of success in supplanting C for many problems. It does this by specializing on certain classes of programs and addressing them with the simplest solution possible. It hasn’t completely replaced C, but it has made a substantial dent in its problem space - more than I can really say for Rust (which has made similar strides for C++, but definitely not for C).

        The kitchen sink approach doesn’t work. Rust will eventually fail to the “jack of all trades, master of none” problem that C++ has. Wise languages designers start small and stay small. Wise systems programmers extend this philosophy to designing entire systems, and Rust is probably not going to be invited. I understand that many people, particularly those already enamored with Rust, won’t agree with much of this article. But now you know why we are still writing C, and hopefully you’ll stop bloody bothering us about it.




        1. DirectoriX
          15.06.2022 10:58
          +2

          Проблема в замещении системных языков — готовые компоненты очень сильно полагаются на другие готовые компоненты. Переписывать имеющийся код (хоть ядро Linux, хоть условный nginx) просто так никто не будет, а если вы уже имеете проект на C (и особенно штат разработчиков на С) — переход на Rust не будет сверхдешёвым, даже если писать на нём только какие-то новые модули: тут сплошной unsafe из-за FFI («а зачем нам безопасный Rust если у нас везде unsafe»), там третьи сутки борются с borrow checker'ом потому что пытаются писать на Rust так же, как привыкли на C («компилятор писать код мешает»). Получается, что на новом языке выгодно писать только что-то совсем новое, а множество таких проектов не очень уж часто пересекается с системным программированием. Хотя есть, конечно, и исключения — например Fuchsia активно использует Rust.
          Насчёт Go, который «has made a substantial dent in its problem space»: основные преимущества Go — быстрое написание кода и простое распараллеливание => в основном микросервисы и микроутилиты. Go в основном отобрал долю рынка у других языков (типа Python), но не у C — ни микросервисы, ни приложения типа «два раза запущу и забуду» на C редко пишут. Даже если почитать «истории успеха перехода на Go» — почти везде будет переход с Python.


          1. Sin2x
            15.06.2022 12:13
            +1

            Го там был дан в пример не как пример системного языка, а как пример философски правильно спроектированного языка, вследствие чего занявшего доминирующее положение в своей нише, дальше которой разрастаться и замусориваться не хочет. Чего нельзя сказать о Расте. Проблема Раста, на мой взгляд, это вообще больше даже не проблема техническая per se, а, скорее, вопрос конфликта отцов и детей. Новое поколение считает, если что-то создано 30-40 лет тому назад, оно по умолчанию не может быть хорошим. Просто вот так вот. Хорошо хоть, аксиомы планиметрии пока держатся иммутабельно.


            1. DirectoriX
              15.06.2022 12:56
              +8

              что-то создано 30-40 лет тому назад, оно по умолчанию не может быть хорошим
              Оно может быть всё ещё хорошим, но за эти 30-40 лет придумали немало новых других хороших штук, поэтому более современные языки не хуже. В случае с тем же Rust — появились проверки на типовые выстрелы в ногу, принудительные. В C сделать, например, buffer overflow вообще элементарно (особенно если работать со строками) но узнаете вы об этом когда будет уже поздно. Да, C-код будет работать чуть-чуть быстрее (возможно), но вам придётся писать существенно больше кода (потому что язык старый и в нём нет мощных конструкций типа match), и у вас будет сильно меньше гарантий, что оно не упадёт из-за какой-нибудь глупой ошибки.
              А уж как приятно отлаживать макросы в чужом коде на C, ммм…


              1. Sin2x
                15.06.2022 14:07
                +1

                Речь, опять же, идёт о том, что энное количество вкусных фич не делают язык хорошим, его делают таковым правильная философия и архитектура. Использовать Си без плюсов как прикладной, а не системный язык, это ССЗБ, бесспорно. Но речь в посте про ядро Линукс.


            1. vabka
              15.06.2022 14:53

              Go системный не в том же самом смысле, в каком системный Си.
              Go предназначен для написания больших распределённых по сети систем, типа Kubernetes или просто каких-то сервисов.
              А Си предназначен больше для работы с каким-нибудь лоу-левелом, как при разработке операционных систем или embedded


            1. cepera_ang
              15.06.2022 17:19
              +1

              Да нормальная у Раста философия. И, как ни странно, большую популярность он имеет как раз у поколения, которое настрелялось в ногу в С, но при этом ещё не закостенело в своих предпочтениях. Вон например чуваки в Oxide Computer делают свои железки с нуля и всю разработку прошивок ведут на расте и молятся на него, говоря, что он, во-первых, позволяет избегать целых классов ошибок, которые призван избегать, во-вторых, браться за амбициозные задачи, типа «а давайте здесь свою ОС напишем с нуля». И это не юнцы какие-нибудь (Bryan Cantrill много всякого интересного написал ещё во времена С).


              1. Sin2x
                15.06.2022 18:15
                +1

                Я довольно хорошо осведомлён о том, что чувствует коммьюнити в целом по отношению к системным языкам, и у меня сложилось впечатление, что все хором сильно топят за Зиг, а вот с Растом ситуация очень divisive -- половина его ненавидит, половина превозносит.


                1. cepera_ang
                  15.06.2022 18:26
                  +1

                  Для существования и успеха вовсе не обязательно, чтобы все любили. А может даже и наоборот нужно вызывать у кого-нибудь ненависть, иначе не считается.


                  А про zig ничего не видел особо, поэтому даже не могу поддержать разговор.


              1. mikhanoid
                15.06.2022 21:41

                OSи пишут на разных языках: Lisp, Java, Haskell, Forth, ML и даже JavaScript. Написать небольшую OS для конкретной железяки - не такой уж и амбициозный проект. У меня второкурсники микроядра с вытесняющей многозадачностью писали за месяц. Человечество уже давно знает, как это делается. В этом плане Rust ничего принципиально нового не предлагает...

                Ну, разве только то, что не получится привычные структуры данных использовать для всяких очередей таймеров или планировщиков пакетов. В этом есть некое интеллектуальное приключение. Но что-то я сомневаюсь, что оно упрощает написание OS, а не усложняет. В той же Redox довольно печально с этим дела обстоят: вместо кучи таймеров активное ожидание с переключением контекстов, очередями событий служат deque и т.д. Не самые эффективные решения, мягко говоря, особенно для систем реального времени.


                1. Sin2x
                  15.06.2022 21:56

                  Redox по-моему всё, умер.


                  1. mikhanoid
                    15.06.2022 22:22
                    -3

                    Типа, не смогли сделать Redox, поэтому пришли в Linux? Опасные ребята...


                    1. Sin2x
                      15.06.2022 23:44
                      +1

                      Нет, всё-таки, месяц назад был релиз: https://www.redox-os.org/news/release-0.7.0/


    1. AnthonyMikh
      15.06.2022 22:58
      +2

      Во-первых, это Дрю. И если для вас это не является красным флагом, то мне вас жаль.


      Во-вторых, вся эта стена текста разбивается в пух и прах двумя предложениями в конце:


      Yes, Rust is more safe. I don’t really care.


      1. Sin2x
        15.06.2022 23:55
        -1

        Учитывая, что это только один пункт из семи перечисленных, после которого идёт "In light of all of these problems", нет не разбивается, и вырывать куски из контекста это, мягко говоря, некорректно.

        При примате safety я бы выбрал Аду, а не раст -- как разработчики NASA.


      1. Omrigan
        16.06.2022 00:26

        А почему Дрю должен быть красным флагом?


        1. AnthonyMikh
          16.06.2022 13:28

          Потому что у него очень свои взгляды на разработку софта, зачастую неправильные. И у него есть софт, которым пользуются люди, только больно падучий почему-то.


          1. Omrigan
            16.06.2022 14:12
            -1

            Потому что у него очень свои взгляды на разработку софта, зачастую неправильные

            Ну взгляды действительно свои и специфические, только взгляды - они не могут быть неправильными, они у каждого свои. Они могут не совпадать с вашими, но они не становятся неправильными.

            По сути же да, они радикальные, тем не менее дают какие-то ценные инсайты, про то как снять ментальную нагрузку при разработке.

            В контексте этой темы я практически со всем согласен, что Rust радикально более сложный язык, и для системного программирования пока нет чего-то более подходящего, чем C с достаточно широким внедрением.

            И у него есть софт, которым пользуются люди, только больно падучий почему-то.

            А что вы имеете в виду? Sway?


          1. Sin2x
            16.06.2022 14:15

            Учитывая, что Sway и wlroots пользуются тысячи человек, это так себе аргумент, даже не принимая во внимание, что ad hominem. На расте проектов масштаба того, что пишет Деволт, я не знаю. Можно было бы назвать фаерфоксовский Servo, но и его пилили-пилили, да так и не допилили.


  1. nikolas78
    16.06.2022 01:01

    О Расте складывается ощущение, что он слишком широко взял, и из-за этого несколько переусложнился. В таком виде на замену C он не очень подходит. На нем было бы удобно писать Linux что-то такое монументально и очень сложное, типа ОС. Но ОС-ы в своей массе уже написаны и с нуля переписываться будут вряд ли.


    1. mikhanoid
      16.06.2022 10:21

      Так как раз ОСы на нём писать крайне неудобно. В этом-то весь цимес. Он слишком ограничивает.


      1. nikolas78
        16.06.2022 15:17

        Тогда остаются высоконагруженные системы реального времени, где цена ошибки очень велика. Но сколько таких заказчиков? Точнее сколько таких типов заказов (ведь один раз написал — продавай везде). Вот интересно как раз в этой сфере продвижение Rust посмотреть.


        1. DirectoriX
          16.06.2022 15:36
          +6

          Ну например вот, особенно

          Cloudflare uses Rust in their core edge logic and as a replacement for C, which is memory-unsafe
          Но какие же разработчики Cloudflare балбесы, ведь в Rust нет безопасного двусвязного списка, зато есть сплошные ограничения на каждом шагу, а проверки могли бы и сами написать /s


        1. Sin2x
          16.06.2022 16:03

          В этой сфере важна стандартизация ISO, поэтому или Си, или Ада. Пока раст не будет стандартизирован, индустрия не будет в нём заинтересована.


          1. cepera_ang
            16.06.2022 16:10
            +1

            Или всё наоборот: раст будет стандартизирован, если индустрия будет в нём заинтересована.


            1. Sin2x
              16.06.2022 16:29

              Нет, не наоборот. В авиации, космической промышленнности, автомобилестроении, медицине и других сферах, где цена ошибки действительно велика -- Cloudflare к таковым не относится -- не будут использовать язык без стандартизации никогда.


              1. nikolas78
                16.06.2022 16:46

                Все таки стандартизация относится больше к менеджменту, чем к технической стороне ЯП. Да и сделать ее можно за достаточное короткоий промежуток времени.


              1. cepera_ang
                16.06.2022 17:43
                +1

                А стандартизация конечно же появляется из воздуха, идёт такой комитет ISO по стандартизации, видит новый язык лежит, берёт его и стандартизирует, чтобы «можно было использовать в авиации, космической промышленности и других сферах», так это по-вашему работает?


                1. Sin2x
                  16.06.2022 18:17

                  По-разному бывает. Си просто стал стандартом де-факто, и после этого был стандартизирован. Ада специально заказывалась Министерством Обороны США под их нужды. В случае раста помимо низкого проникновения в индустрию мешает то, что язык как таковой ещё не финализирован самими авторами, он всё ещё work in progress.


                  1. cepera_ang
                    16.06.2022 18:46

                    То есть, если будет достаточно интереса, то стандартизация последует? А пока будет набирать популярность в mission critical проектах, но не в safety critical.


                    1. Sin2x
                      16.06.2022 18:58

                      Не вижу препятствий, кроме необходимости иметь какую-то завершённую спецификацию.


              1. 0xd34df00d
                16.06.2022 19:35

                В таких сферах используют и какой-нибудь coq, который не стандартизован и не будет стандартизован никогда.


          1. nikolas78
            16.06.2022 16:45

            .


          1. 0xd34df00d
            16.06.2022 19:35
            +1

            Возьмём, например, HFT. Цена ошибки высока? Очень, можно и присесть при особой неудачливости. Высоконагруженная система? Да. Реального времени? Нет, круче: в реальном времени вам надо гарантировать выделение (или завершение) задачи какого-то времени, а здесь вам надо соревноваться с другими, очень финансово мотивированными людьми.


            Аду там не используют вообще. С — наверное, кто-то использует, но я лично с такими товарищами не знаком. Все, с кем я знаком и с кем работал, используют либо плюсы, либо смотрят в сторону своих кодогенераторов, либо стали интересоваться растом.


            1. Sin2x
              16.06.2022 20:14

              В HFT, которые известны мне, используют Скалу, Кложу и Окамл. Это другая область. Сейчас, может, и на раст стали смотреть.


              1. 0xd34df00d
                16.06.2022 22:11

                Все эти языки с gc и очень геморройными возможностями контролировать его задержки, так что T у вас там не очень HF.


                1. Sin2x
                  16.06.2022 22:56

                  Их это не смущает, значит, это не такая большая проблема, как кажется. Видимо, функциональная парадигма важнее с её проверками корректности.


                  1. 0xd34df00d
                    17.06.2022 00:08
                    +1

                    Их это не смущает, значит, это не такая большая проблема, как кажется.

                    Значит, ещё раз, это не HF.


                    Видимо, функциональная парадигма важнее с её проверками корректности.

                    Ну, тут окамл со скалой тоже дают не так много гарантий. Мы в своё время смотрели на то, чтобы свой собственный DSL сделать.


                    1. Sin2x
                      17.06.2022 02:00

                      Я не трейдер, но насколько мне известно, то, чем занимается Jane Street, это именно HFT, у них окамл.