Comments 24
А для чего Rust в прошивке? Чем он поможет, что он улучшит?
А для чего Rust в прошивке? Чем он поможет, что он улучшит?
В каком месте автор указывает на улучшение использования Rust в отличии от Си и ассемблера? Если внимательно почитать статью, можно обнаружить, что
Именно с идеи попробовать и сравнить началось мое путешествие по написанию EFI-утилиты на Rust для BIOS.
то есть потому что почему бы и нет?
Т.е. статья из серии "Дум на стиральной машине"?
Так а в чём проблема написать прошивку на языке, который позволяет писать прошивки?
Да бог в помощь, я же разве против? Только брингапить хоть сколько-нибудь новое железо на этом будет очень, очень тяжело. Ну вот так тяжело, что я бы даже пробовать не стал, в взял бы EDK, или, что не менее вероятно, коммерческий BIOS.
А тяжело будет потому, что в прошивке 99.9% проблем носят железный характер, а не то, каким именно пузырьком сортируется список PCIe устройств.
Поэтому залезание сырым языком в очень сложный эмбед видится мне скорее спортивным мероприятием, нежели претендующим на какой-то прод.
Не буду спорить со сложностью эмбеда (не моя стихия), но кажется, что автор и сам туда не лезет с сырыми языками, а просто пишет на Rust UEFI-аппку.
Можете ли вы аргументировать про "сырой язык"?
Например на микроконтроллерах STM32 библиотеки на Rust значительно менее сырые, чем официальный HAL на С.
Сужу исключительно по распространенности в эмбеде.
Что касается STM32 и его знаменитого HALа - писал и пишу с использованием HAL, железо в проде, брат жив.
Распространенность вообще ортогональна сырости. Есть куча примеров популярных сырых технологий и непопулярных отточенных. Другие аргументы про "сырой язык" будут?
Что касается HAL. Вы же не будете спорить, что STM32 HAL на каждый чих делает кучу действий, которые в нормальном коде занимают 1-2 такта?
А как насчет поддержки всех режимов работы периферии? Как в нем выключить только Noise Error, не выключая Framing Error в UART? Как написать раельно работающий SPI Slave, или еще хуже I2C Slave? Каждый раз приходится после функций HAL менять вручную биты в регистрах.
Сделать кастомное USB (не CDC или HID) устройство вообще не возможно. Проще полностью выкинуть код USB из HAL, и написать свою библиотеку USB.
Знаете, у меня I2C slave и SPI slave (да еще и в ненормальном режиме, он читает SGPIO) в одном устройстве работают прекрасно, единственное место, в котором я лезу куда-то мимо HAL - вызов встроенного загрузчика.
Вообще-то все рассуждения о STM32 к топику отношения не имеют. И ваши трудности с настройкой железа к выбору языка программирования тоже отношения не имеют.
Вероятно вы просто не сталкивались с этими проблемами. Например, если SPI Master раньше времени отпустит CS, то SPI Slave (проверено на STM32F103 и STM32F411) зависнет в неопределенном состоянии, т.к. в сдвиговом регистре будет от 1 до 7 бит. И при следующем включении SPI он начнет с этого места, а не с 0 бита. Лечится это обычно сбросом тактования SPI, о чем HAL естественно не знает, и молча делает дичь.
И ваши трудности с настройкой железа к выбору языка программирования тоже отношения не имеют.
Но ведь это вы изначально заявили про "сырой язык". Согласен, давайте его обсуждать. Какие будут ваши доказательства?
дубль
"Наука не терпит вопроса «почему». Главный вопрос — «почему бы и нет». Почему наши исследования так опасны? Почему бы не заняться чем-нибудь менее опасным? Действительно, почему бы не изобрести безопасную дверь, которая не ударит вас по заднице по дороге отсюда, потому что вы уволены!"
Моя версия: например, если человек лучше умеет работать с rust, чем с С, а такие поди уже есть и со временем станет больше таких людей. Также, чтобы пользоваться удобной системой сборки, вместо всего того, с чем надо иметь дело в Си. Ещё, в более сложном приложении весь unsafe будет в отдельном месте, а в основной логике будет safe rust, чтобы было меньше типичных для Си ошибок.
Вопрос вроде бы и простой, но ответ получается объёмный. Лично моё мнение, на данный момент, полностью вытеснить Си невозможно просто в силу объёма кода, написанного на нём. Сейчас можно частично написать или переписать лишь какие-то элементы, например, Dxe-драйвера, утилиты, работающие в шелле, попадался мне как-то даже загрузчик на Rust. Если говорить о чем-то более раннем, инициализация стека, памяти, железа — тут сложнее, но думаю возможно.
Про сам язык, попробовав для себя отметил, опять же в сравнении, как разработчик, что язык даёт более удобные инструменты для работы с динамической памятью, забирает всю работу с освобождением на себя. Очень частая проблема связана с утечкой памяти, так как ты можешь это упустить или забыть просто в силу частоты появления такого события. Да, это не критично, утекают килобайты, до мегабайтов редко доходит, но всё равно неприятно.
Еще мне понравилась в языке тема с обработками результатов работы - Result. Это убирает из кода “простыни” с обработкой выхлопа из функций, позволяя сосредоточиться на главном функционале, а не на бесконечном количестве if-в с обработкой статуса.
И можно привести еще примеры с прикормкой из языка, от которой я балдею. Опять же, для себя я решил, что пока пробую rust только для написания утилит, и на данный момент мне всё нравится
DXE переписать? Там примерно 680к строк кода из примерно 1.6М. Сколько займет человеко-лет?
Динамическая память? Вот в этих 1.6Е6 строках кода содержится 232 вызова malloc(). Ради 232 вызовов мы перелопатим 1.6 миллиона строк?
Утечка памяти в программе, которая работает от силы 5 минут? Утечка в килобайты - некритична? Я, конечно, не знаю за фронтэнды и бэкэнды, но в тех задачах, которые решаю я, утечка памяти просто недопустима.
Я ничего не имею против Rust, как и против любого другого языка, но на мой взгляд, во встраиваемой разработке, к коей относится и UEFI, он сегодня не применим.
И вообще, я все понимаю про взрывной рост IT, но, может, вместо изобретения языка, который защищает от ошибок программиста, можно нанять квалифицированного для выполняемой работы?
Чтобы он и тесты написал, и, может, не только написал, а и стенд построил, чтобы на целевом железе тестировать, и на осциллографе углядел, например, как настройки контроллера памяти влияют на глазковую диаграмму.
Ах, это не дело программиста - глядеть в осциллограф и паять стенд? Так это эмбед, тут именно так работают.
Переписывать всю фазу DXE и все драйвера не предлагаю, это что-то на безумном. Можно, как идея, новые драйвера пробовать писать изначально на нем. Если буду пробовать, то постараюсь поделиться опытом с сообществом.
Вообще идея переписывания ради переписывания мне не очень близка, но в этом правиле могут быть исключения. Допустим, бывают такие случаи, когда нужно переделать под проект драйвер, и эти изменения могут копиться как снежный ком: в начале понемногу, а потом через полгода понимаешь, что под лавиной из твоего кода похоронены старые исходники драйвера. В этот момент можно, если есть возможность и желание, подумать, как это всё причесать, чтобы и читаемость улучшить, и архитектуру подправить, и вспомнить про тех счастливчиков, которые будут всё это поддерживать в дальнейшем. И тут, как мне видится, Rust — хороший инструмент.
Из минусов: кушает больше памяти, высокий порог, работает медленнее. Это может быть критично, если говорить про МК, но если про использование в BIOS, тут это не так заметно.
Пару слов про аллоцирование. Может показаться, что 232 вызова — это немного, но тут главная проблема - с какой частотой происходят вызовы? Отвечу на свой вопрос: часто, очень часто. Память выделяется и при получении handler-ов, и при работе со строками, может происходить просто аллоцирование через функцию. И по опыту, ты можешь это всё держать в голове, и в описании функций это указано, но просто в силу человеческого фактора можно случайно такое пропустить из-за объема. И это по большому счету работа, которую можно оптимизировать, и Rust как раз это делает. Мелочь, а может для кого-то и нет, но приятно. Позволяет подумать о чем-то более важном.
Квалифицированный программист - это хорошо, но мы же говорим про язык, а это просто инструмент. И всегда хорошо иметь под рукой классный инструмент, который имеет предохранители от "брака", но язык позволяет эти предохранители отключать. В крайнем случае можно разные участки работ делать разными инструментами.
Мне тоже понравился раст, даже очень (пакетный менеджер из коробки и удобная система сборки вообще как манна небесная), но честно, я не понимаю манию переписывать всё на Rust. Написать что-то новое — почему бы и нет, только за. Но тратить время на переписывание того, что уже работает, очень сомнительная затея. Может получиться как https://habr.com/ru/companies/ruvds/articles/842970/ (TL:DR, переписали часть кодека с C на Rust, ассемблер не тронули, а всё стало работать на 6% медленнее)
забирает всю работу с освобождением на себя.
Да, это не критично, утекают килобайты, до мегабайтов редко доходит, но всё равно неприятно.
То есть в RTOS системах его использовать нельзя? Или в IoT устройствах где зачастую не больше 10k RAM?
Ну, я например не вижу особого смысла переписывать всё с C/C++, слишком много переписывать придётся. Язык — это просто инструмент. Можно писать небезопасно на Rust, можно писать безопасно на C/C++ (санитайзеры вам в помощь). Единственное что — из-за неформализованности компилятора Rust я бы не стал его использовать в safety-critical (где я и работаю). По сути моя единственная претензия :)
Аргументы в стиле "безопасности по памяти" там, где приходится писать unsafe код, ровно как и "сырость Rust", ну это же всё чушь, серьёзно. Имхо, любой аргумент что против, что в защиту Rust это почти всегда передёргивание.
Согласен с вами, что язык - это просто инструмент, и он не может быть всегда универсальным. Пример, который вы привели, мне очень нравится, потому что он подтверждает это.
Если говорить про RTOS и МК, то тут не вижу смысла использования Rust. Си позволяет тут выстроить более тонкую настройку.
Я наоборот вижу в нем смысл именно для МК, RTOS или драйверов ОС.
1) Библиотеки. Ничего уровня embassy или defmt в С нет и не предвидится. В С++ кстати тоже.
2) Безопасность. Нет множества UB, которые в С приходится проверять санитайзерами, хотя это просто не должно было скомпилироваться.
3) Быстродействие. Ассемблер на выходе такой же, а местами и чище чем в С, т.к. у компилятора больше возможностей для оптимизации.
Ну и памяти есть меньше, см. например null pointer optimization, который вообще не возможен в С.
А бригада по моему с гуашью будет?
Вижу Миранду Косгров, ставлю плюс.
Применение Rust в UEFI/BIOS