Михайлов Алексей Анатольевич @MinimumLaw
Linux Kernel, Bare metal, Embedded developer
Information
- Rating
- 2,473-rd
- Location
- Пушкин, Санкт-Петербург и область, Россия
- Date of birth
- Registered
- Activity
Specialization
Embedded Software Engineer, Software Architect
Senior
From 350,000 ₽
А такая постановка вопроса заставляет нас задуматься в другом ключе: программирование это ремесло или искусство?
Я начинал, когда оно было искусством. Как и схемотехника, и многие другие сферы. Потому умом соглашаюсь с Вашими доводами, но сердцем ругаю «серых троечников» от программирования.
Посмотрим. Технически практически во всех сферах есть область «ширпотреба» и область «hand maid'а». От пиво- и самогоноварения, через кулинарию и Hi-Fi до авиастроения. Наверное, в этом что-то есть. И, вполне возможно, что рано или поздно дойдет очередь и до программирования.
Так точно. Завтра найдется хитрая и крайне редко возможная (и не возможная принципиально у меня) возможность переполнения, которую исправят ценой производительности и поломают все мои критичные ко времени выполнения участки. Я именно про это.
Я тут только в процессе. Учусь и присматриваюсь. Если честно, то я пока не понял насколько это востребовано в моем варианте. Асинхронный код, запускаемый по обработчикам прерываний на bare metall (которые по природе асинхронны) — это вкусно. Я умею такое на С, но что с этим делать на Rust я пока не представляю. Посмотрим…
Но знаю… Давайте я осторожно скажу, что не уверен. Тема математического доказательства безопасности — не мой конек, но множество архитектур железа наводит на некоторые мысли о том, что не все safe действительно всегда и везде будут безопасны. Впрочем, еще раз — не мой конек. Готов принять на веру что в этой части все сильно лучше, чем кажется.
Черт его знает. Может быть это просто уже привычный кактус. И он не так колется. Или просто привык выкусывать мякоть и не попадаться на колючки.
А может и наоборот — многолетняя практика ошибок выявила все возможные места, которые могут трактоваться программистами по разному. И узаконила их. Если так, то где гарантия что с ростом популярности и количеством сторонних компиляторов любой язык не обрастет чем-то похожим?
Ну, бенчи и профилировщики в bare metall это редкие гости. Просто в силу проблемности реализации. Это все же не прикладной код под D-Trace'ом.
А вот следить за тем какой код получается — это точно. Но тут-то как раз и ловушка. Оставлять unsafe — значить писать как на C. А зачем, если есть С? Ставить safe — разменивать скорость на безопасность, но это же можно и на C. Только там я контролирую процесс, а тут? В лучшем случае баланс сильно смещается в безопасность. Но устроит ли меня такой вариант? Больше того, для кода с safe никто не обещает гарантированного времени выполнения. Т.е. то густо, то пусто… Неприятно. Впрочем, это мои задачи. И это специфика bare metall. Для прикладного ПО, пожалуй, это все не столь критично.
Но в целом чем дальше, тем больше спор напоминает спор автомобилистов. Одни кричат, что у нас безопасность и удобство: коробка автомат, ABS, ESP, EBD, BA, на крайний случай ремни и подушки по кругу, вторые кричат что безопасность — это мастерство водителя и возможность тотального контроля поведения машины, который ни одна электронная система никогда не перехватит. По мне спор этот будет длиться еще очень и очень долго. Но рано или поздно победа так или иначе будет за автоматами. Тотальный контроль если и останется, то будет нишевым решением. Так и с языками. Останется С где-нит на самом нижнем уровне. А все, что выше планировщика — все будет на чем-то «безопасном».
От себя могу добавить только одно — довольно молодой язык. С ещё не устоявшимся API. Боюсь, что до тех пор пока выход каждой новой версии может сможет сильно изменять двоичный результат не о каком широком практическом применении речи быть не может. Это, кстати, отчасти и является причиной того, что даже C++ не приживается во встраиваемых системах. Уж больно часто его дергают. А вот чистый C, как «кросплатформенный ассемблер» давно устоялся. И если и идут работы вокруг него, так только в части исправления откровенных косяков компиляции и оптимизации runtime библиотеки (опять же, которую во встраиваемых системах стараются использовать самым минимальным образом).
Впрочем, надо посмотреть. Только время все расставит по своим местам. Пока Rust любопытен. Пожалуй, я готов его изучать, но точно не готов писать не нем то, что уйдет в массовое производство. Пока есть сомнения. И в том, что это кто-то кроме меня сможет сопровождать, и в надежности результата в том числе. Да, последнее скорее всего напрасно, но пока оно есть — не о каком программировании для изделия речи не будет. Только «на побаловаться». Ну и скорость… Куда ж без нее. Такты наше все. Чем меньше их съем я, тем больше их останется тем кто выше.
Но, справедливости ради, давайте отличать травы и грибы. Биологически это совсем не одно и тоже.
Подавляющее большинство народного фольклора — ложь. Но где ее больше — в байке про лягушку или в том что масло из молока взобъется миксером — тот еще вопрос. Уж поверьте человеку, который масло взбивал просто тряся банку в руках. Меня так теща проверяла. На готовность к женитьбе. Тоже местная традиция.
О-хо-хо… Меня все детство травками лечили. И сейчас дома как у хорошей знахарки. Но все сам правильно заготовлял. Подавляющее большинство аптечных — кроме как сеном назвать у меня язык не повернется.
А так любимые успокоительные варианты, такие как пустырник, валериана и некоторые другие вообще опасно пить просто так. Уж слишком много побочки (думаю, как раз безумное количество сена в составе их и спасает). Более народные средства типа мёда и других продуктов с пасеки работают лучше.
Так что серьезен я. Более чем.
Ну да. Только вся статья и 90% комментариев про то, что специалистов мало. А тех, кому безоговорочно доверять можно — так вообще практически нет.
И я про тоже пишу. Если повезло — то повезло. Если нет — главное не прекращать брыкаться. Кто ищет — тот находит, кто не ищет, тот и не найдет.
Вопрос только в том, что верить гуглу в части поиска выхода из такой ситуации — то еще решение. Оно и для рабочих задач практически никогда не помогает (в лучшем случае наводку дает), а для личных, особенно таких деликатных — так практически никогда.
Вот и получается что оказываешься в роли лягушки в крынке. Пока брыкаешься шансы есть. Вопрос лишь в том, что раньше случиться — масло взобъешь или силы кончатся. Но не будешь брыкаться — точно утонешь. Отсюда спорт, смена хобби, работы, жены… И хорошо, если попадется толковый доктор, который хотя бы сон исправит правильными препаратами, а не пустышками с лекарственными травками. Уже легче будет.
Но все равно — только сам. Пусть и через боль, и через не могу. Нет другого пути.
Мы вступаем на скользкую дорожку противоборства веры. Вашей веры в то, что стройная система типов — главная часть компилятора. против моей веры в то, что компилятор ценен весь, включая runtime. Я даже не буду вспоминать про то, от чего зависит прочность цепи. Веру нельзя перебить аргументами.
В конце-концов я описывал всего-то свое впечатление от Rust. При чем пока оно следствие крайне поверхностного знакомства с этим языком. Другое дело, что и подход к нему был как «к еще одному из рода», а не как к «универсальному способу писать безопасный код».
Потому я просто соглашусь.
Хорошо, но ведь компилятор Rust'а не Моисей на скрижалях принес. Т.е. в конечном счете все так или иначе упирается в квалификацию авторов. Хорошо, не библиотеки, а компилятора. Но разве это что-то принципиально меняет?
Не готов судить прямо сейчас. Но ознакомлюсь. Все может быть…
Хорошо. Но согласитесь — по сути мы говорим об одном и том же. Просто мое понимание более общее, а Ваше — более каноническое.
Смотрите, процессор знает лишь очень ограниченное количество типов. И в подавляющем большинстве случаев не умеет их расширять или защищаться от переполнений. Да даже преобразование одного в другой не всегда доступно. Все что выше — это уже вопрос грамотной организации доступного. Разве нет? И ровно так же
Это не аппаратный блок процессора, а только надстройка над существующими (если хотите дырявыми) аппаратными решениями. И делает ее часть языка.
Собственно у голого C проблема ровно в отсутствии таких языковых конструкций. Согласен, не очень канонично считать и то и другое стандартной библиотекой языка, но ведь по сути это именно она. Только используется для реализации типов и операторов, а не встроенных функций и внешних процедур.
Ну, я поправился на тему Prolog и Lisp. Хотя и тот и другой имеет и циклы, и присваивания, и сравнения, и массивы в каком-то виде. Да что там — всеми любимый brainfuck имеет все необходимое. Правда тут вопрос что считать полномасштабными операциями, но… Я склонен считать, что они есть и тут.
Попробуйте. Я буду рад узнать язык, который этого не содержит.
P.S.
Патефон и музыкальную шкатулку не предлагать. Согласен, там тоже в некотором смысле программа, но она изначально линейная и ветвлений впринципе не предусматривает.
Мои воспоминания из детства несколько другие. Правда тут уже конец 80-ых… Поселек в 130 км от Ленинграда. Заводов нет, ничего нет. Из б/у только резисторы. Лампы в дефиците — все идут на ремонт «рекордов» и радиол. За то посылторг — это кладезь. Тут все — и химия для фотографии и радиокомпоненты из ширпотреба (МП39, МП41, КТ315) — и очень не дорого. Даже для меня, зарабатывавшего первые деньги на уборке картофеля. Оттуда же и диоды. Радиолюбительство было доступно. Посылторг тогда — это практически современный алиэкспресс. С тем же «то ли привезут, то ли нет, то ли через месяц, то ли через год». Но это работало. Детекторный приемник у нас работал. Но крайне плохо и тихо. А вот вывести «маяк» из усилителя оказывалось сильно сложнее, чем собрать приемник способный его поймать.
Да и вообще — четко помню внутренний конфликт. Собрать и отладить одним только тестером и пробником даже довольно сложную схему на 6-7 транзисторах оказывалось проще, чем найти батарейки для ее работы.
А вот цифровых микросхем нет от слова совсем. РУ'шки и РФ'ки просто никак, РТ'шки дорого и без гарантии… Да и банальную логику брать было просто негде. Сосед сверху собирал спектрумы и за запчастями ездил «на толпучку» в Питер. Автово, теперяшняя Юнона, магазин «Юный техник»… Когда я первый раз туда попал — это, конечно, был шок. При чем даже не от запчастей, а именно от толпы народа. Мне больше нравился магазинчик радиодеталей на Бассейной ул. И рядом магазин «Электроника». Там все же поспокойнее было, да и присутствовал практически все, что мне тогдашнему было надо.
Но не сказал бы, что это было массовым увлечением. В школе даже кружка не было. Все сам. По книгам и собственными шишками. Хотя, вру. С чем-то помогали мастера из телеателье. Но как помогали… Они, в отличии от родителей, хотя бы не ругались. Уже дорогого стоило.
А про «радиохулиганов», собственно, только в журнале «Радио» и читал.
Однако позволю себе вопрос не по теме. Скажите, а Вы саму гидру смотрели? Есть некоторые опасения. Все же очень серьезный инструмент, класса IDA Pro, да бесплатно, да еще от АНБ. Как-то сильно попахивает бесплатным сыром, место которого вполне известно. Что-то я не вижу, чтоб хоть кто-то хоть как-то поанализировал саму гидру на тему скрытой функциональности. А было бы достаточно любопытно.
Увы, языка на котором может быстро, безопасно и грамотно писать обезьяна еще не изобретено. И крайне маловероятно, что он хоть когда-нить появится. Потому «мастер не должен ошибаться» парадигма вечная и не зависящая от сферы деятельности и используемых инструментов. И в равной степени относится как к строителям и продавцам в Пятерочке, так и к IT'шникам вообще и программистам любых направлений в частности.
А ощущения… Так они субъективны. У каждого мастера свои предпочтения в части инструмента. Кто-то фанатеет от Makita, кто-то от Bosch, а кому-то и Hummer «не настолько хуже, насколько дешевле». Стоит ли непосредственно ассоциировать качество итогового продукта с инструментом, которым он сделан?
С другой стороны, конечно, мастер выбирает инструмент под себя. Ибо не подходящий по уровню инструмент может испортить всю задумку и конечное изделие. Но главный парадокс в том, что обратное совсем не гарантированно. Новичку можно выдать супер-дупер-мега классный инструмент, но из-за неумения им пользоваться он моментально затупится, разобьется или еще что-то похожее, и очень быстро станет соответствовать уровню владельца. С другой стороны, толковый мастер легко
подкует блохупереберет и починит бьющийHummer и подточит резцы.
Как всегда — есть множество крайностей. Встречаются люди, свято уверенные в том, что мастеру надо выдать веревку. А уж камень для топора и деревяху для ручки он и сам найдет. А дальше сам себе со временем все инструменты сделает. Увы, такое тоже не редкость.
Или наоборот. Люди свято уверенные в том, что любую проблему можно решить просто дав одномоментно много денег. Таких меньше, но все же есть. Увы, и этот вариант не работает.
Потому и к данной статье вопросов нет. Мастер выбрал инструмент, мастер сделал. И ведь не скажешь что некрасиво сделал. Наоборот. А в учебных целях так просто здорово. Мало ли мы в школе на черчении загогулин чертили, в реальной жизни не встречающихся.
Ладно, отмазу написал, теперь можно и по делу…
Да по сути все языки одинаковые. Особенно низкоуровневые. Присвоения, циклы, математические и логические операции, управление памятью. Ничего нового ни один язык не преподносит. По сути они и отличаются только библиотекой и очень незначительными деталями в реализации базового функционала. Привет Алану Тьюрингу.
И нет принципиальной разницы, чем он «ворочает». Хоть объектами, хоть физическими байтами. Все равно все в конечном итоге скатывается лишь к тем операциями и с теми ограничениями, на которые способен процессор. Да и все процессоры, при всем их богатстве: от AVR и 8051 до ARM и MIPS, через Эльбрус и SPARC мало чем друг от друга отличаются.
Практически, даже не важно для физической или для виртуальной машины язык плодит код тот или иной язык. Виртуальная машина практически ничем не отличается от физической. Во всяком случае со времен Кнутовского MIX'а мало что поменялось. И между ним и JAVA больше сходства, чем отличий.
Через некоторое время приходит понимание простой истинны — знаешь один язык, знаешь все. Ладно, не все. Языки класса Prolog и Lisp стоят в сторонке, но к счастью они не столь часто встречаются «в дикой природе». А остальные практически близнецы.
А почему же их так много? Да все просто — каждый язык находит свои задачи. Обратное тоже верно — каждая крупная задача производит для себя язык. Нужна была обработка текстов и анализ на спам — родился Perl (Raku?). Нужна была генерация страниц — появился PHP. Нужно моделирование реального мира — C++ с сотоварищами. Да мало ли примеров — они у всех на устах.
И с таким подходом Rust реально мало чем отличается от C. Давайте исключим синтаксис (он, как известно, дело вкуса разработчиков языка и только) и посмотрим что останется. А останется… Ну да, безопасная работа с массивами данных. А за счет чего? Правильно, за счет усложнения кода стандартной библиотеки языка. Она вобрала в себя все Best Practice и прочие наработки по данному вопросу. А по другому и быть не может — никаких новых аппаратных блоков, нацеленных на безопасность обработки блоков данных в процессорах не появилось. Надеюсь, теперь мне простят сравнение Rust и C.
А нужен ли при таком раскладе C (тот, который без плюсов)? По мне нужен. Он как раз является тем самым «кросплатформенным ассемблером» и при этом как и положено ассемблеру не имеет никакой специализации. Я не вижу на горизонте языков, которые могли бы так же. Да, был в свое время Pascal. Но он сильно сдал.
Вот так как-то. Не судите строго. Еще раз повторюсь — это скорее для обсуждения в курилке или под пиво, чем для Хабра.
Про остальное — да не очень-то и хотелось. В конце-концов я больше думаю, чем пишу и фишки типа автопереименования переменных или автодополнения мне не нужны. Больше того — мешают, ибо почти всегда работают неправильно. В том же Atmel Studio. Уж на что в основе Microsoft Visual Studio, а такая лажа со всеми этими фантиками.
Я же и не спорю. Просто привык к тому, что мои задачи не требуют особой тригонометрии или медиан. Но крайне критичны ко времени реакции системы. Да и начинал учиться у ассемблерщиков. А те ребята занятные. С одной стороны кроссплатформенный ассемблер на сплошных макросах, с другой жутко платформо-специфические оптимизации. До сих пор не понимаю как это могло уживаться в одном человеке. Но так и пошло — то, что переносимо, то на С, что сильно критично ко времени, то… тоже на С, за очень редким исключением. Как правило нет нужды в трюках с платформой, достаточно применить более толковый (но более непонятный) алгоритм. Ну и прагмами или ключами компиляции побороться с излишне умным компилятором.
Наверное, когда-нить, на других задачах я возьму и плюсы. Но пока у меня «мышление на С». Больше 10 лет работы непосредственно программистом, и еще 15 в учениках, да над очень сходными задачами даром не проходят… Вон, даже тот же Rust с трудом воспринимается. Хотя, казалось бы — те же яйца, только в профиль.
В IAR это так:
...
define block PROG_SPECIAL with alignment = 16, size = 0x80 { section .prog_id_data };
...
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec, block PROG_SPECIAL };
...
Для GCC так
...
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
.prog_id_data :
{
. = ALIGN(16);
KEEP(*(.prog_id_data)) /* PROG identification data */
. = ALIGN(16);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
...
}
И в коде программы как-то так:
Все. Секция всегда помещается сразу за векторами. А размер таблицы векторов — уже дело компилятора.
Про остальное — ну, вот именно этот момент меня и задерживает от перехода на плюсы. Грамотный аллокатор — штука не самая простая. К тому же довольно компромисная в части скорость-фрагментация. Очень не хочется терять такты и/или в нужный момент оказываться без необходимой памяти. Но еще раз — я согласен, это подход динозавров. Потому пока динозавры хоть кому-то нужны я предпочту «закатывать солнце вручную». Потом придется переучиваться, но это же потом…
Можно, но ведь всегда идем путем наименьшего сопротивления. Занулить или забить патерном кучу разницы никакой.
Размещение контролирую — обязательно. Всегда хорошо сделать сразу после векторов секцию с писанием что это, когда собрано, а в идеале еще и коммит. Крайне удобно «в полях» — когда не знаешь что именно и когда именно залито было.
Нецелевое использование… Ну да, не здорово. С другой стороны — а чем куча будет отличаться от массива? Я ее принципиально в своем коде не использую. Вся память у меня распределяется на этапе компиляции. Пока, во всяком случае, удавалось справиться так.
Уже давно ссылка на описание не работает, но IAR даже на -Onone упорно выделял сдвиги и маски в функции, чем сильно ухудшал производительность. Потеря 20% на абсолютно ровном месте. GCC таких вольностей себе не позволял не только на -Onone, но и на более высоких уровнях. Позже этот же код был портирован на ARM (с поправкой на 32-разрядность) и там IAR повел себя так же паскудно. С тех пор я ему не верю и регулярно проверяю что именно он делает «на выходе». Если очень кратко — не нравится мне его работа. Местами шибко умный, а местами тупой как пробка. Посмотрите сами на свой код — думаю много интересного обнаружите.
Впрочем, у Вас плюсы… Вам сложнее… Или проще… Даже не знаю.