Что интересного в архитектуре и компиляторе «Эльбруса» — узнаем в новом выпуске «Битовых масок»
Вы наверняка слышали не одну новость о российских процессорах «Эльбрус», но вряд ли могли удовлетворить профессиональное любопытство в теме. Вам поможет подкаст «Битовые маски»! В новом выпуске гостем стал Виктор Шампаров — разработчик компилятора LCC для весьма специфической линейки процессоров «Эльбрус» на базе архитектуры VLIW (Very Long Instruction Word).
Виктор провел подробную экскурсию по особенностям «Эльбруса» и архитектуры VLIW с точки зрения системного программирования. Кроме того, Виктор как опытный преподаватель оценил, как сегодня осваивают компиляторы студенты технических вузов.
Среди тем подкаста:
почему сложно сделать хороший компилятор под VLIW;
в чем разница между советским и российским «Эльбрусом»;
что в компиляторе «Эльбруса» написано с нуля;
какие особенности есть у VLIW-компилятора;
почему в архитектуре «Эльбруса» сравнительно больше регистров;
зачем в «Эльбрусе» санитайзер оптимизации;
в каких вузах стоит учиться работе с компиляторами.
Смотрите и слушайте подкаст на любой удобной платформе — и присоединяйтесь к каналу «Битовых масок», чтобы не пропустить новые выпуски!
Как разработать Linux-драйвер реального устройства для платформы RISC-V
Если вы хотите лучше разобраться во внутреннем устройстве Linux и узнать, как его ядро взаимодействует с физическими устройствами, то приходите на бесплатный офлайн мастер-класс YADRO. Вместе пройдем полный цикл создания драйвера дисплея LCD1602 для VisionFive2: от теории до добавления новых функциональных элементов и запуске на одноплатнике.
Что будем делать:
загрузим информацию о дисплее в ядро через Device Tree Overlay;
выведем текст на дисплей через драйвер Linux для embedded-систем;
считаем содержимое дисплея из ядра Linux и выведем в консоль;
научимся управлять подсветкой и курсором через интерфейсы Linux Kernel Driver;
займемся обработкой IRQ по нажатию кнопки;
разберем типичные ошибки при разработке Linux-драйверов.
Мастер-класс проведет Никита Косырев, инженер-программист группы системного ПО в YADRO. Никита — энтузиаст embedded-систем и архитектуры RISC-V, несколько лет занимался разработкой драйверов периферийных устройств в ядре Linux.
Приглашаем инженеров, которые хотят лучше разобраться в низкоуровневой разработке для Linux и особенно тех, кто работает с user space-приложениями.
Мастер-класс пройдет офлайн 3 июля в московском офисе YADRO, количество мест ограничено. Участие бесплатное, но регистрация обязательна.
kettlebell — статический генератор блога на AT&T Assembler, под i86pc Solaris 11.4
Пост-анонс. У меня есть лог, что-то среднее между блогом и микроблогом — там я пощу коммерческую рефлексию: заметки про продажи и архитектуру принятия решений.
Сама идея лога появилась недавно, но мыслей для него насобиралось уже порядочно. Пока оформляю просто верстая HTML, но это мягко говоря не удобно. Естественно задумался о статическом генераторе сайтов (SSG), но не брать же чужой когда ты инженер?
Выбор на чём написать свой оказался не простым. Выбирал между мейнстримом (Go, Rust) и андеграундом (Ada, APL). На APL у меня уже есть генератор, поэтому решил поднять планку. В итоге выбрал ассемблер.
Пишу под Solaris, без зависимостей, только сисколы. Solaris потому что она мне нравится и я под ней работаю; чтобы там не говорили — это инженерный шедевр.
Проект пишется в свободное время как инженерный манифест. Когда SSG будет полностью готов, я выкачу сюда, на Хабр, большой технический лонгрид с архитектурными графами, полным разбором системных вызовов и инструкцией для тех, кто захочет пощупать это вживую.
Полный список планируеммых команд (из инженерного черновика):
# Полная сборка всех новых статей
> ./kettlebell
# Пересобрать все статьи
> ./kettlebell --force
# Пересобрать все статьи, предварительно удалив папку ./build
> ./kettlebell --clean --force
# Собрать статьи только для 1 языка, только новые
> ./kettlebell --lang ru
# Пересобрать все статьи для 1 языка
> ./kettlebell --lang ru --force
# Генерация только 1 поста для 1 языка
> ./kettlebell --post ru/new-idea
# Перезаписать существующий пост или элемент в RSS
> ./kettlebell --post ru/llm-as-lvr --force
# Создать блан для поста во всех языках
> ./kettlebell --new last-bastion
Если вы уже пробовали агент в JetBrains IDE или просто следите за тем, как меняется разработка с AI, загляните и проголосуйте ссылка на голосование Ваше мнение поможет нам понять, что важно разработчикам, и развивать продукт в правильном направлении.
Хочется проверить, насколько разработчикам близка идея AI-агента, который работает не вслепую по grep и длинным логам, а использует IDE как источник фактов: структуру проекта, зависимости, ошибки компиляции, тесты, конфигурации запусков и поведение приложения.
Будем рады голосам, комментариям и особенно критике. Она помогает точнее объяснять, чем Veai отличается от чат-ассистента, который не видит проект так, как его видит IDE.
Если у вас есть опыт с Cursor, Continue, JetBrains AI Assistant или другими инструментами, тоже приходите в обсуждение. Нам важны честные сравнения, а не стерильный маркетинговый текст.
Стать системным аналитиком в YADRO — дело трех дней
До 29 марта открыта программа быстрого найма для системных аналитиков. Таких специалистов ищут сразу две команды:
— Телеком. С нуля создают телекоммуникационные решения для беспроводных мобильных сетей и сопутствующих услуг. Разрабатывает первые российские базовые станции стандартов GSM/LTE.
— BIOS/BMC. Инженеры занимаются разработкой и сопровождением собственных программных реализаций ПО UEFI/BIOS и BMC, используемых в различных продуктах YADRO.
Формат быстрого найма подразумевает ускоренные прохождение технического и менеджерского интервью и возможность получить оффер в компанию за три дня.
Направления, где нужны аналитики:
OAM (Operations, administration and maintenance). Специалисты тут работают с системой, обеспечивающей эксплуатационную управляемость и устойчивость операторского уровня. Отвечают за сквозные сценарии эксплуатации — от конфигурирования и мониторинга до инцидентов, SLA и масштабирования.
GSM. Здесь разрабатывают GSM Controller (BSC) и компоненты базовой станции (BTS) стандарта GSM с поддержкой GPRS и основного функционала для операторов большой тройки.
LTE. Инженеры здесь создают базовую станцию LTE (4G), реализуя полный стек телекоммуникационных протоколов «с нуля».
BIOS/BMC. Как уже писали выше, здесь занимаются разработкой и поддержкой UEFI/BIOS для продуктов компании, кода BMC для мониторинга и управления серверами, а также прошивками для MCU- и FPGA-модулей серверов (материнские платы, экспандеры и так далее).
Подробнее об ожиданиях к кандидатам — на лендинге SPRINT OFFER. Успейте оставить заявку до 29 марта.
Компания Zhipu AI совместно с Университетом Цинхуа представила одну из важнейших открытых моделей 2026 года — GLM-5. Это не просто инструмент для написания кода, а полноценная система, способная самостоятельно планировать проекты, создавать код, проводить тестирование, устранять баги и улучшать решения в течение длительного времени.
Основные характеристики GLM-5 впечатляют: - Архитектура MoE с общим количеством параметров 744 миллиарда, из которых одновременно активируется лишь 40 миллиардов. - Контекст длиной до 200 тысяч токенов позволяет хранить целиком большие кодовые базы. - Первый открытый релиз с оценкой 50 баллов по индексу AAI. - Лидирует среди открытых моделей в тестировании LMArena (оценка текста и кода). - По уровню производительности сравнима с закрытыми моделями уровня Claude Opus 4.5 и Gemini 3 Pro.
Изначально модель была выпущена анонимно под именем Pony Alpha, вызвав предположения, что это продукт от крупных западных компаний вроде DeepMind или OpenAI. Однако вскоре выяснилось, что разработка принадлежит китайской стороне, подчеркивая значимость проекта.
Технические особенности включают: - Обучение на массиве из 28,5 триллионов токенов. - Использование технологии Sparse Attention, снижающей вычислительные затраты на обработку больших объемов контекста. - Асинхронный метод обучения с использованием RLHF, позволяющий эффективно задействовать ресурсы GPU. - Трехступенчатое обучение, включающее этапы рассуждений, агентирования и выравнивания.
Практические достижения: - Высокий показатель успешности тестов на платформе SWE-bench Verified (77,8%) и лидерство в тесте BrowseComp (75,9%). - Модель обучалась на большом количестве репозиториев GitHub (более 10 тыс.). - Способность успешно управлять бизнес-процессами, включая моделирование реального бизнеса (например, сеть торговых автоматов).
Особенность GLM-5 заключается также в оптимизации под китайские процессоры Huawei Ascend, Cambricon и Kunlun, обеспечивающую производительность, аналогичную западным платформам, но с экономией примерно на 50%.
Таким образом, появление GLM-5 свидетельствует о том, что разница между открытыми и проприетарными системами практически исчезла. Открытые модели теперь способны решать реальные инженерные задачи на мировом уровне, работая на собственном оборудовании и показывая конкурентоспособные результаты.
Вывод очевиден: эпоха закрытых систем уходит в прошлое, а гонка технологий становится настоящим соревнованием, где качество продукта важнее бренда.
Греческие мифы рассказывают про титана Прометея, который украл у богов огонь и поделился им с людьми. Персонажа за это приковали к скале не просто в наказание, но и в назидание остальным: знание не даётся бесплатно, за него нужно платить.
Если судить по названию, автор проекта Promethee кары богов нисколько не боится. Некто SMNX взял самый сакральный слой современного компьютера — прошивку UEFI — и добавил туда JavaScript. Как гласит readme.md, на старте загрузки Promethee подхватывает script.js с загрузочного тома и исполняет его, то есть этот скрипт и будет загрузчиком.
Понятно, что на боевую машину это ставить смысла нет, это просто эксперимент. Лабораторный характер подчёркивается сборкой и запуском в QEMU. Проект реализован автономно (freestanding), с минимальными заглушками libc. В качестве движка используется Duktape — встраиваемый JS-движок, рассчитанный на портируемость и компактность.
Для SMNX это уже не первый подобный забавный самопис. На своём сайте автор представляется как Клем и прямо говорит, что любит строить «операционные системы, компиляторы, инструменты и веб-движки». Там же перечислены другие поделки: модульная хобби-операционка SkiftOS, HTML/CSS-движок Vaev, экспериментальные инструменты для генерации документов, а также операционная система с эстетикой брутализма и идеалами UNIX семидесятых BRUTAL.
JavaScript исторически задумывался как язык, который оживляет веб-страницы и делает их интерактивными. Сегодня же он расползся по всем слоям стека, от микроконтроллеров до ультра-лёгких движков для Интернета вещей. В том числе бывают попытки писать на JavaScript то, что не следует, хоть операционные системы. Самый цитируемый пример — это NodeOS, дистрибутив Linux, где вместо привычного пользовательского мира предлагается использовать Node.js и npm как основной пакетный менеджер, и многие утилиты предполагается брать из npm-экосистемы. Другой полюс — runtime.js, библиотечная операционка, где JavaScript-рантайм на базе V8 и минимальная операционка собираются в лёгкий неизменяемый образ виртуальной машины для запуска на KVM, то есть ОС здесь становится упаковкой для единственного приложения на JS.
Когда мне пришла в голову мысль что я хочу навайбкодить операционку, у меня было смутное представление что полноценным успехом можно будет считать только self-hosted OS, то есть чтоб в ней запускались дев-тулы, можно было поправить исходники, скомпилировать, ребутнуться с новым ядром и все продолжало работать.
Если честно, я не думал что получится, думал в лучшем случае получу что-нибудь что может запустить пару kernel-space процессов которые будут по очереди что-то в UART печатать и все. А оно раз, и получилось… Self-hosting milestone взят!
В Slopix есть: - Простенький шелл - Компилятор Си (и прочие build essentials) - Интерактивный редактор текста с подсветкой синтаксиса для Си
Принципиально ничто не мешает теперь заниматься разработкой слопикса в слопиксе.
Потребовалось 5 weekend sprints. Получилось примерно 45к строк на Си. Узнал много нового про операционки и многому научился в плане coding agents workflows. Ну и тонну удовольствия получил, конечно же!
Открытый мультиплатформенный проект Deletor умеет удалять ненужные и вредоносные файлы, кэш после рабочей сессии, улучшает производительность вашего SSD. Решение написано на Go.
Открытый проект All In One USB Drive содержит необходимые ISO-образы для восстановления компьютерной системы на ПК, включая установщики ОС, драйверы и все необходимые полезные сервисы для воскрешения системы и нормальной работы, а также инструкции ко всем сервисам.
Ускоренный найм для инженеров C/C++: оффер за 3 дня
Телеком-команда YADRO создает решения для мобильных сетей нового поколения: базовые станции GSM и LTE, а также весь программный стек — от низкоуровневых протоколов до систем управления. Сейчас в команде открылись вакансии инженеров, отбор на которые можно пройти гораздо быстрее, чем обычно.
SPRINT OFFER — это формат ускоренного найма: все этапы отбора проходят всего за три дня. Чтобы попасть в программу, достаточно подать заявку до 19 октября.
Software Engineer (телеком-платформа)
Вам предстоит разрабатывать платформенное решение для телеком-систем. На его основе строятся современные узлы сотовых сетей LTE- и GSM-стандартов — например, базовые станции и системы управления. В это роли вы будете:
Развивать платформу, обеспечивающую middleware-сервисы, высокую доступность и управление узлами для приложений, входящих в состав базовой станции LTE/GSM.
Разрабатывать компоненты платформы в технологическом стеке C++/Linux.
Собирать и анализировать метрики для оценки производительности продукта.
Создавать и оптимизировать высокопроизводительные каналы коммуникации между компонентами, а также работать с подсистемами временной синхронизации, управления конфигурацией инфраструктуры и компонентов.
Поддерживать средства развертывания и обновления приложений.
Разрабатывать API для взаимодействия с аппаратным обеспечением и операционной системой при конфигурации и управлении инфраструктурой.
Обеспечивать качество продукта: исправлять дефекты, писать unit-тесты, проводить код-ревью, разрабатывать техническую документацию.
Создавать инструменты, упрощающие работу других разработчиков.
Участвовать в диагностике и анализе проблем работы системы в тестовых и полевых сценариях.
Создавайте высоконагруженные системы, которые обеспечивают стандарты связи разных поколений. Работа охватывает три уровня. L1 — низкоуровневое программирование, работа с радиоканалом и сигналами, близкая к железу. L2 — логика, работа с алгоритмами и математическими моделями. L3 — высокоуровневое программирование, бизнес-логика. В этой роли вы будете:
Разрабатывать решения совместно с командой — от этапа исследования и прототипирования до коммерческого внедрения пакетного ядра сети 5 поколения (5G).
Создавать программное обеспечение для базовых станций LTE, реализуя полный стек протоколов 3GPP.
Разрабатывать спецификации и дизайн программного обеспечения.
Интегрировать решения с другими компонентами системы — как программными, так и аппаратными.
Поддерживать и оптимизировать код, обеспечивая стабильность и производительность продукта.
Исследовать и устранять проблемы, влияющие на надежность, производительность и масштабируемость системы.
Мне бы очень хотелось стать инженером-строителем. Изучаю физику,но иногда это тяжело дается.Хотелось бы представлять ,как работают формулы в жизни.
Хочу научиться делать простенькие визуализации.
Посоветуйте,пожалуйста,с чего начать.Может,есть понятные сайты или программы,где такое можно создавать?Мне бы что-то для старта,чтобы поскорее увидеть результат и лучше понять физику.
Заранее спасибо за любую наводку🌷 Вы мне очень поможете!
MCP архитектура как развитие ручного подхода в LLM
Когда вы открываете ChatGPT и вставляете туда кучу текста — что реально происходит? Всё складывается в один длинный «бутерброд»: данные, инструкции, системный промпт, даже куски схемы в Markdown. Никакого порядка. Это как если бы у вас в кодовой базе был один файл main.py, где и роуты, и бизнес-логика, и SQL-запросы.
Я хочу описать идею MCP кратко, поскольку в самой доке она не описана. А может быть даже и не закладывалась туда. Но очень похоже, что такая архитектура хорошо работает исходя из более фундаментальных принципов, чем просто разделение
Как это выглядит у ChatGPT
На схеме выше видно:
Есть Line Edit — пользователь копипастит сырые данные.
Есть Плагин — иногда он что-то подмешивает.
Всё это сливается в один большой Склеенный промпт, который уходит в LLM.
Мешанина как она есть
Как это делает MCP?
MCP приходит и говорит: «ребята, давайте хоть модули разнесём».
System Prompt — отдельная часть, где живёт логика «как правильно жить» для модели.
Instruction Layer — патчи и локальные корректировки.
Schema Registry — отдельный каталог, который описывает структуру данных (таблицы, поля, форматы).
Data Adapter — слой, который достаёт данные у провайдера строго по схеме.
Всё это связывает MCP хост, который собирает финальный запрос к LLM, который зачастую представляет собой Lang Chain
Итог: модель получает запрос не как «мусорный мешок», а как структурированный pipeline.
Почему это важно
Прозрачность. Можно отследить, какая часть отвечает за что.
Контроль. Можно менять системный промпт без страха поломать данные.
Расширяемость. Хочешь новый источник данных? Добавь адаптер, а не переписывай всё.
Предсказуемость. Поведение модели становится ближе к детерминированному.
Простая метафора
ChatGPT — это когда у вас «final_final_v3.docx» и все правят его параллельно.
MCP — это когда у вас git с ветками, пайплайнами и CI с CQRS архитектурой (не шутка), читай выше
Зачем работать напрямую с клиентом, когда можно просто выкинуть запрос на MCP и дать нейросети подумать? 😎
Расскажу кейс Vivo Chat. Проверка статуса заказов (замените на вашу сущность). Давайте по порядку
Клиент идёт к хосту, чтобы получить доступ к MCP
Итак, наш клиент — это тот, кто первым инициирует запрос. Всё начинается с того, что клиент заходит в свою систему, которая подключена к MCP-серверу через хост. Хост выполняет функцию посредника, направляя запросы и получая ответы от разных компонентов системы.
Клиент: «Привет, хост, мне нужно проверить заказ, и я хочу понять, что из инструментария MCP мне пригодится. Покажи мне, пожалуйста, список доступных инструментов и подсказок, чтобы я мог выбрать что-то нужное для этого запроса.» Хост (перехватывает запрос и направляет его к серверу MCP): «Окей, сейчас все передам.»
Хост запрашивает у MCP список инструментов (Tools) и подсказок (Prompts)
Хост теперь идёт к MCP-серверу. Этот сервер знает всё, что связано с доступом к данным и обработкой запросов. В MCP сервере хранятся все инструменты (tools) и подсказки (prompts) для выполнения нужных действий.
Хост: «MCP, подкинь мне список доступных tools и prompts для запроса клиента.» MCP-сервер: «Вот, держи, вот все инструменты и подсказки, которые у нас есть. Для каждого метода я также подготовил параметры, которые можно подставить.»
LLM, любимая нейросеть, выбирает метод из списка
Теперь, когда хост получил список инструментов и подсказок, он передает всё это в LLM (нейросеть), которая и будет решать, какой метод нужно использовать для конкретного запроса.
Хост: «LLM, тебе пришёл запрос от клиента. Вот список инструментов и промптов. Тебе нужно выбрать подходящий метод для выполнения запроса и подготовить все нужные параметры для этого метода.» LLM: «Хорошо, я выбираю метод X из списка инструментов, и вот какие параметры мне нужны для этого метода. Я знаю, что нужно сделать, и использую соответствующие промпты, чтобы точно понять, что клиент хочет.»
LLM передает параметры и вызывает метод на MCP
Теперь, когда LLM выбрала нужный метод и подготовила параметры, она отправляет всё это хосту, который, в свою очередь, передает запрос обратно в MCP-сервер для выполнения.
LLM: «Вот всё, что мне нужно: метод X и параметры для выполнения. Передавай это на MCP.» Хост: «Принято, иду к MCP.»
Хост направляется к MCP-серверу и передает запрос на выполнение метода.
MCP выполняет метод и возвращает результат
MCP-сервер теперь, получив все необходимые данные, выполняет метод и обрабатывает запрос. Всё, что нужно, уже у него под рукой: инструменты, параметры, контекст. Вся обработка происходит внутри MCP, и сервер возвращает результат хосту.
MCP-сервер: «Я выполнил метод X с этими параметрами. Вот результат: (ответ).»
Ответ от LLM клиенту
Теперь, когда MCP выполнил метод, хост получает ответ и передает его обратно в LLM, которая уже анализирует результат, добавляет необходимые детали (например, форматирует или уточняет ответ) и отдает всё клиенту.
Хост: «Вот ответ от MCP через LLM: (ответ). Всё готово!» LLM: «Отлично, теперь я передаю результат обратно клиенту.» Клиент: «Вау, всё так быстро! Спасибо, LLM!»
Итог
На мой взгляд в бизнес-приложениях — это самый частый кейс, а всё остальное, связанное с обновлениями статусами заказов, удалениями данных будет упираться в безопасность и комплаенс
Я уже писал, из чего состоит протокол, как выглядят сервер и клиент, и зачем вообще всё это проксирование. Теперь — шаг вперёд: как вся эта архитектура живёт в реальных приложениях.
Если смотреть на схемы выше, то картина получается парадоксальная. Уровень связности высокий: запросы к LLM проксируются через хост, а MCP-сервера сидят как отдельные острова, каждый тянет свои данные — базы, файлы, API. На первый взгляд хочется спросить: «зачем такие сложности?». Ответ простой — тарификация и контроль. Если бы сервер напрямую ходил к LLM, владелец MCP оказывался бы заложником чужой экономики. А так запрос идёт через клиента/хост, и именно пользователь контролирует, когда и какой токен уходит в модель.
Важно понимать: MCP-сервер всегда на стороне провайдера данных. Это он готовит промпты, пишет функции, агрегирует источники. Ваша задача — не изобретать велосипеды, а собрать этих провайдеров, подключить через MCP и дальше использовать уже в своих оркестраторах (хоть LangChain, хоть самописные пайплайны).
Почему MCP имеет значение? Всё зависит от того, где вы стоите: – Разработчику MCP сокращает время интеграции и даёт готовый слой абстракций. – ИИ-приложениям MCP открывает экосистему источников и тулзов. – Пользователю MCP гарантирует, что его данные не уходят вслепую, а действия согласованы.
В сухом остатке: MCP — это не про «ещё один протокол», а про баланс удобства и контроля. Пример банальный, но показательный: пользователь хочет слетать в Барселону. Серверы MCP подтянули календарь, историю поездок, поиск рейсов и отелей. Агент сложил всё в кучу и забронировал отпуск за минуты. Задача, которая вручную заняла бы часы.
В следующей части разберём, какие паттерны интеграции MCP-серверов с LLM-оркестраторами реально просто работают
В прошлой статье я рассказывал о редком, но весьма опасном баге: поток под Windows зависал в вызове CancelIoEx, хотя документация Microsoft утверждает обратное. Суть проблемы — в пересечении синхронного и асинхронного ввода-вывода, где ядро Windows блокирует доставку APC, и поток остаётся навсегда «висящим».
История получила развитие не сама по себе: мы целенаправленно поднимали эту тему через support-кейс в Microsoft. В результате удалось подключить и Escalation Team, и разработчиков Go, ответственных за Windows-порт.
Финальный вывод: стандартная библиотека Go действительно использует неправильный API для отмены синхронных операций. Вместо CancelSynchronousIo, рекомендованного самой Microsoft, в коде до сих пор вызывается CancelIoEx.
Менее радостная часть: из-за сложности изменений и их влияния на рантайм правка запланирована только в Go 1.26 (февраль 2026). Бэкпорт в предыдущие версии практически исключён.
Что это значит для разработчиков
Если ваш сервис на Go под Windows внезапно «зависает» в CancelIoEx — это следствие бага в стандартной библиотеке, а не ваша ошибка.
До релиза Go 1.26 остаются обходные варианты:
не вызывать CancelIoEx для синхронных дескрипторов,
использовать CancelSynchronousIo, если есть возможность управлять потоками,
минимизировать использование пайпов в критичных местах.
Итог
Редкий flaky-тест Go (TestPipeIOCloseRace) оказался симптомом реальной и серьёзной проблемы. Благодаря эскалации через Microsoft Support и совместному разбору мы получили подтверждение, понятное объяснение и официальный фикс в планах.
⚡️ Если ваш Go-код на Windows зависает в CancelIoEx, теперь вы знаете: проблема признана и исправление уже в пути.
Почему я больше никогда не буду использовать сервис bitly?
В общем я обычно достаточно аккуратен со всякого рода скамом, редко попадаю в такие ситуации, обычно хорошая чуйка на такие истории, но в этот раз не обошло меня стороной.
Long story short: помогают тут ребятам с одним оффлайн проектом, нужно было быстро сделать QR код для флайеров, google выдает миллион сервисов для генерации, выбрал первый попавшийся “Create Your Free QR Codes”. Удачно все сделал, заказали флаеры, не смотря на то, что по пути на каждому этапе было Free через 2 недели (когда уже все напечатано) прилетает вежливое “Oh no! Your Dynamic QR Codes will expire in 3 days”. И конечно же он перестанет работать если не заплатить ($20/month).
Масштаб “потерь” - $40, но я готов заплатить $200 чтобы объяснить они строян бизнес на скаме и для кармы это вредно.
Конечно же я не один такой, и большинство “сжимают зубы” и платят. Например на редите 230 комментариев.
Как вы поступаете в такой сиутации? Я как-то с детства считаю что нельзя потокать и платить.
Мои действия:
✅ никогда в жизни ни на одном из моих проектов не будет использоваться сокращалка Bitly
✅ написал далобу в FTC
✅ написал отзыв на Google Maps (там таких много)
☑️ найду и напишу отзывы на других сервисах
✅ попрошу вас помочь мне и присоединиться
P.S. Ресеч показал, что это не просто какие-то горе стартаперы, а проект компании Bitly (рейтинг 1.6 на Trustpilot).
Если вам нечем заняться и вам не сложно уделить 2-5 минут своего времени.
Промпт для генерации отзыва:
Write a concise, neutral review of qr-code-generator.com (Bitly) in plain, easy-to-read language, 80-120 words. Context: It appears in Google for queries like "free qr code generator." During setup, the process is presented as free; any expiration notice, if present, seems absent or buried in terms. About 14 days later, the QR may be deactivated behind a paywall, leaving printed materials unusable unless payment is made to reactivate. The system does not allow converting that now paid QR to a free static code or redirecting it without payment. Many users report similar experiences online, including numerous Reddit comments. Keep the tone calm, factual, and non-accusatory. Do not include personal info or insults. Write in your own words.
Места куда стоит запостить отзыв:
- Google Maps (Bitly Office Google Maps)
- Trust Pilot
- G2
- Capterra
P.P.S. Есть кто-то из СМИ хочет изучить эту историю и написать подробнее - я буду рад ответить на вопросы и предоставить материалы.
P.P.P.S. Особенно иронично выглядит позиция “Head of Happiness” в подписи письма
В прошлой статье мы пришли к выводу, что QMP — это лучше, чем ничего. Но хочется большего — библиотеку или программу (желательно, уже готовую), которая умеет читать/писать и узнавать об изменении состояния через poll() / pselect() / select() / epoll() / read().
В таком случае для каждой модели GPIO нужен «клей», похожий на тот, что используется с chardev — мы включаем его прямо в модифицированный QEMU. Очевидное название такого «клея» — gpiodev. Вот его основные функции, которые сейчас почти полностью соответствуют GPIO UAPI в Linux:
сообщать количество линий, конфигурацию, название и потребителя каждой линии,
читать и задавать состояние линии,
отслеживать изменения состояния и конфигурации линии (вход/выход, запрос/освобождение).
«Клей» состоит из двух групп, первая — это индивидуальные для каждого модуля GPIO функции, которые gpiodev использует, чтобы запросить специфическую информацию:
LineInfoHandler() — информация о линии: имя, флаги и потребитель,
LineGetValueHandler() — состояние линии: условный 0 или 1,
LineSetValueHandler() — задать состояние линии: 0 или 1.
По аналогии с GPIO UAPI напрашиваются также функции LineGetMultiValueHandler() и LineSetMultiValueHandler() для запроса и выставления линий, но я решил ограничиться минимальным набором.
Можно ли организовать прозрачное взаимодействие с устройствами внутри QEMU — использовать те же библиотеки и инструменты, как и для реальных устройств? Читайте во второй части трилогии о долгом пути до GPIO в QEMU.
Как облачные сервисы продвигают продукты на хакатонах
Хакатон — способ поднять узнаваемость бренда и расширить воронку найма, все хорошо это знают.
При этом немногие учитывают, что хакатон — еще инструмент продвижения свой продукта среди разработчиков.
Облачные сервисы успешно этим пользуются. Ниже несколько кейсов с выводами.
Все топовые облака: Amazon, Google Cloud, Azure, Cloud.ru, VK Cloud, Yandex Cloud провели хакатоны в последние 3 года.
Самый масшабный был с призовыми в $150 000.
К участию приглашались стартапы для решения социально значимых задач. Единственное требование — использовать сервис в своем решении.
В РФ сильнее всего отметились Selectel и Cloud.ru, тогда под брендом SberCloud.
На SberCloud Advanced Hacking собралось 70 команд из малого и среднего бизнеса. Они внедряли облачные технологии в свои продукты — самые оригинальные решения получили призы.
Всего мы проанализировали 10 хакатонов от облаков. Делимся выводами.
Хакатоны облачных сервисов выделяются необычно взрослой аудиторией: как правило, ЦА — средний и малый бизнес. Это потенциальные клиенты.
Задачи ставятся максимально широко. Ограничения бывают А) по тематике, например, «сделайте что-то социально значимое», Б) по технологии, например, собираются решения в области AI, Web3, Blockchain, IoT. Это идеально для хакатона.
Максимум по участникам в РФ — около 260 человек. Есть простор для яркого крупного ивента.
Вывод: облачные сервисы и вообще все, кто производит продукт для разработчиков, одним махом закрывают сразу 3 задачи с помощью хакатона:
продвинуть продукт
поднять узнаваемость бренда
расширить воронку найма
Если ваша компания относится к таким — донесите ценность до бизнеса, это поможет «продать» идею хакатона внутри и оставить всех довольными.
Что ты сделал для хип-хопа IT-инфраструктуры в свои годы? Писал UEFI и BMC для высоконагруженного оборудования
В YADRO есть распределенная команда, которая разрабатывает и сопровождает собственные программные реализации UEFI (BIOS) и BMC. Для самого разного оборудования — от серверов до телеком- и клиентского оборудования.
Реализуют программную поддержку новых аппаратных продуктов компании, определяют протоколы и методы взаимодействия между программными и аппаратными компонентами продуктов YADRO.
Проводят верификацию микрокода и выполняют проверку прошивок микросхем всех продуктов компании. Выстраивают стратегию тестирования.
Исследуют новые программные и аппаратные технологии для применения в продуктах. Рефакторят код для повышения производительности.
Придумывают методы безопасного обновления прошивок BIOS и BMC, чтобы обеспечить минимальный или нулевой даунтайм.
Добавляют новые фичи и меняют существующие — от WebUI до политик управления аппаратными компонентами.
Команде нужно больше инженеров — разработчиков на С/C++, тестировщиков, автоматизаторов и техлидов. Знакомься с вакансиями на сайте и вовлекайся в трушные инженерные задачи на современном технологическом стеке.
Решил по фану реализовать конвертор милей в километры на C. Ссылка тут.
Advanced distance converter: miles to kilometers
Usage: ./bin/fib_miles2km [OPTIONS] [distance]
Options:
-h, --help Show help information
-f, --fib=ARG Convert miles to km using basic Fibonacci
-b, --basic=ARG Convert miles to km using standard formula
-i, --fib-interp=ARG Convert using Fibonacci interpolation
-c, --fib-cache=ARG Convert using cached Fibonacci
-g, --fib-golden=ARG Convert using golden ratio
Предлагаю два варианта, которые я условно решил назвать MMIO и PCI. Последний — тоже MMIO, но в QEMU они добавляются разными путями. Начнем с сердца любой MMIO-модели — апертуры.
Апертура и адресное пространство
Как я упоминал в одной из своих статей, любое MMIO-устройство — это MemoryRegion с заданными шириной доступа и размером. Для того, чтобы он был виден CPU или другому устройству, такому как DMA, его нужно разместить в соответствующем адресном пространстве — например, пространстве, назначенном для cpu0:
Фактически это означает, что все семейство инструкций Load/Store будет вызывать mmio_gpio_register_read_memory()/mmio_gpio_register_write_memory() при совпадении адреса чтения/записи с адресом региона в адресном пространстве.
Передаваемые аргументы и возвращаемое значения интуитивно понятны. Отмечу, что hwaddr addr — это адрес относительно начала нашего региона, а не абсолютный адрес.
Нам остается лишь создать устройство и добавить его регион в файле машины:
Почти десять лет назад Никита Шубин, ведущий инженер по разработке СнК в YADRO, сделал возможность чтения и записи GPIO для QEMU. Читайте первую часть трилогии о долгом пути до GPIO в QEMU.
На днях в офисе я столкнулась с коллегами из направления системного программирования в «Криптоните». Они пишут на С++ — а ошибки на этом языке у нас ещё не было!
Поэтому я попросила их придумать код с ошибкой специально для Хабра — и вот что получилось!
Итак, есть ли в этом коде проблема кроме narrowing conversion? Ждём ваши варианты в комментариях.
#include <cstdint>
#include <vector>
struct Type
{
Type(uint16_t, uint32_t = {})
{}
};
int main()
{
std::vector<Type> vector;
std::uint32_t object_id{};
// Есть предупреждение о narrowing conversion
vector.insert(vector.begin(), {0, object_id});
// Нет narrowing conversion
vector.push_back({0, object_id});
// Нет narrowing conversion
vector.insert(vector.begin(), Type{0, object_id});
}
АККУРАТНО, ДАЛЬШЕ СПОЙЛЕР!
Проблема в том, что в строке
vector.insert(vector.begin(), {0, object_id});
в вектор вставляется 2 элемента типа Type, а не один, как ожидает программист.
Причина в том, что метод insert у вектора имеет перегрузку (номер 5), которая вторым параметром принимает std::initializer_list. А компилятор, видя фигурные скобки в коде, в первую очередь пытается создать объект такого типа.
И тут ему это удается, потому что у конструктора Type второй параметр имеет значение по умолчанию, следовательно, Type умеет создаваться, если в конструктор передали только один аргумент. В итоге компилятор успешно создает std::initializer_list с двумя элементами типа Type.
Так как создание std::initializer_list выполняется с использованием uniform initialization, то компилятор следит за корректностью преобразований. В примере объект типа std::uint32_t передается в конструктор Type, который принимает первым параметром std::uint16_t. То есть, возникает риск потери точности (32 бита не могут поместиться в 16 бит).
Об этом компилятор и предупреждает. Вот упрощенный пример, где видим то же самое предупреждение.
Может возникнуть вопрос, почему создание Type от 0 не вызывает предупреждение, ведь 0 - это int, а он, скорее всего 32 бита и тоже не помещается в 16 бит. Но тут литерал. Компилятор видит, что 0 вмещается в 16 бит и не предупреждает. Но если поместить int в переменную, то также возникает предупреждение.
Устройство компилятора (кратко) на LLVM Компилятор - инструмент конвертации исходного кода, написанного на высокоуровневом языке программирования в машинный код, который может исполнять компьютер.
Компилятор делится на 3 этапа:
FRONTEND - анализирует текст исходного кода и преобразует его в IR.
MIDDLE - анализирует и оптимизирует этот сгенерированный код IR.
BACKEND - преобразует IR в машинный код.
Сам компилятор, и собственно язык программирования состоит из нескольких частей.
Lexer - лексер
Лексер сканирует и превращает сырой текст в токены. То есть сам исходный код разбиваеты на набор токенов (такие как литералы, идентификаторы, ключевые слова, операторы, разделители) Лексер читает исходный код символ за символом и идентифицирует последовательности символов, соответствующие определённым правилам языка.
Парсинг
Парсинг немного сложнее чем лексический анализ. Существует множество паресров и парсеров-генераторов.
Парсеры в компиляторах обычно принимают входные данные в форме токенов и строят определенное дерево - AST или дерево парсинга.
Обычно компиляторы строятся из множества маленьких компонентов, которые берут входные данные, меняют их или преобразуют их в различные выходные данные. Это одна из причин, по которым функциональные языки хорошо подходят для создания компиляторов. Другие причины — прекрасное сопоставление с эталоном и довольно обширные стандартные библиотеки. Прикольный факт: первая реализация компилятора Rust была на Ocaml.
Советую держать эти компоненты как можно более простыми и автономными — модульность сильно облегчит процесс. По-моему, то же можно сказать и о многих других аспектах разработки ПО.
AST
AST - абстрактное синтаксическое дерево. Это структурированное представление исходного кода программы в виде дерева, где каждый узел дерева представляет собой синтаксическую конструк языка программирования. Это дерево предоставляет абстракцию, которая позволяет анализировать и манипулировать программным кодом на высоком уровне.
IR
Эта часть занимается созданием [[1.2 IR]]. Через примитивы LLVM мы можем сгенерировать промежуточное представление. Каждому типу в AST дается метод, называемый codegen, который всегда возвращает объект значение LLVM, используемый для представления одного регистра присваивания (single assignment register), который является переменной для компилятора, которая может быть назначена только один раз. Интересно, что в этих примитивах IR то, что в отличии от ассемблера, они не зависят от какой-либо конкретной архитектуры машины, и это значительно упрощает работу для разработчиков языков, которым больше не нужно сопоставлять вывод в набор инструкций процессора. Теперь, когда фронтенд может генерировать IR, инструмент LLVM Optimizer используется для анализа и оптимизации сгенерированного кода. Он выполняет несколько проходов по IR и выполняет такие действия как устранение мертвого кода и скалярная замена агрегатов, и, наконец, это приводит нас к бекенду, где мы пишем модуль, который принимает IR в качестве входных данных, который выдает объектный код, который может работать на любой архитектуре.
Главной особенностью LLVM является промежуточное представление кода (англ. Intermediate Representation, IR), форма, которую использует LLVM для представления кода в компиляторе. LLVM IR был разработан для выполнения функций промежуточного анализа и преобразований внутри оптимизатора компилятора. Ее создание имело целью решение множества специализированных задач, включая поддержку легковесных оптимизаций среды выполнения, кроссфункциональные и межпроцедурные оптимизации, полный анализ программы и агрессивные реструктурирующие преобразования. Промежуточное представление кода определено как язык первого порядка с четкой семантикой.
IR (Intermediate Representation) в контексте LLVM — это промежуточное представление кода. Это низкоуровневое, независимое от платформы и типобезопасное представление программного кода, которое используется в качестве промежуточного языка между интерфейсной частью и серверной частью компилятора.
Этот код LLVM IR соответствует следующему коду на языке C, обеспечивающему возможность сложения целых чисел двумя разными способами:
unsigned add1(unsigned a, unsigned b) {
return a+b;
}
// возможно не самый лучший способ сложения двух чисел
unsigned add2(unsigned a, unsigned b) {
if (a == 0) return b;
return add2(a-1, b+1);
}
Как видно из этого примера, LLVM IR — низкоуровневый RISC-подобный набор виртуальных инструкций. Как и настоящий набор инструкций RISC, он поддерживает линейные последовательности простых инструкций (сложение, вычитание, сравнение и ветвление). Эти инструкции имеют трехадресную форму. Это значит, что они берут некоторое количество входных данных и вычисляют результат в другом регистре. LLVM IR поддерживает метки и в целом выглядит как необычная форма языка ассемблера.
Строго говоря, промежуточное представление LLVM является четко определенным и единственным интерфейсом оптимизатора. Это означает, что всё, что необходимо знать, чтобы писать фронтенды для LLVM, это: что такое LLVM IR, как он работает и какие инварианты ему необходимы. Так как LLVM IR имеет текстовую форму, то имеет смысл создавать фронтенд, который выводит LLVM IR в виде текста, а затем отправляет его на оптимизатор и необходимый генератор кода при помощи каналов Unix.
Рэймонд Чен — ветеран компьютерной индустрии, который работает в Microsoft c 1992 года. Рэймонд участвовал в разработке OS/2, Windows 95, DirectX и оболочки Windows, а последние десятилетия отвечает за сохранение обратной совместимости системы. В своём блоге Old New Thing Чен регулярно делится забавными историями из разработки софта, но также показывает действительно полезные примеры.
На этот раз Чен показал, почему история буфера обмена не отражает быстрые изменения содержимого буфера. Рэймонд приводит следующий фрагмент кода от клиента. Этот код был написан для некой утилиты, вставляющей в историю буфера обмена объекты. В некотором роде историю прошлых изменений превращали в будущее — целью было предугадать, какие элементы пользователь хотел бы видеть в истории буфера обмена.
// В целях наглядности вся проверка ошибок опущена
#include <windows.h>
void SetClipboardText(HWND hwnd, PCWSTR text)
{
OpenClipboard(hwnd);
EmptyClipboard();
auto size = sizeof(wchar_t) * (1 + wcslen(text));
auto clipData = GlobalAlloc(GMEM_MOVEABLE, size);
auto buffer = (LPWSTR)GlobalLock(clipData);
strcpy_s(buffer, size, text);
GlobalUnlock(clipData);
SetClipboardData(CF_UNICODETEXT, clipData);
CloseClipboard();
}
// Чтобы они были под рукой, разместим эти строки в истории буфера обмена
static constexpr PCWSTR messages[] = {
L"314159", // номер бага, который мы хотим исправить
L"e83c5163316f89bfbde7d9ab23ca2e25604af290", // коммит, к которому привязываем ошибку
L"Widget polarity was set incorrectly.", // комментарий, который нужно добавить
};
int wmain([[maybe_unused]] int argc,
[[maybe_unused]] wchar_t* argv[])
{
auto tempWindow = CreateWindowExW(0, L"static", nullptr, WS_POPUPWINDOW,
0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
for (auto message : messages)
{
SetClipboardText(tempWindow, message);
}
DestroyWindow(tempWindow);
return 0;
}
Код записывает в буфер обмена последовательно три строковые переменные. Однако при запуске утилиты в истории буфера обмена оказывалась лишь одна — последняя. Куда делись две остальные?
Дело в том, что служба истории буфера обмена работает асинхронно через механизм Clipboard Format Listener, существующий с эпохи Windows Vista. В этом механизме через функцию AddClipboardFormatListener приложение добавляет себя в качестве листенера. После этого никаких дополнительных опросов буфера обмена проводить не нужно — система сама оповестит приложение, если буфер изменился.
При получении уведомления служба истории буфера обновляет собственно историю буфера обмена. Но из-за асинхронности событие может происходить с задержкой. Как объясняет Чен, из-за асинхронной природы обновлений при получении WM_CLIPBOARDUPDATE от Clipboard Format Listener буфер может успеть обновиться ещё раз.
Как считает Рэймонд, это даже не баг, а фича. Так получается избегать приложений, которые быстро спамили бы в буфер обмена множество изменений. Если даже пользователь не успевает воспользоваться содержимым буфера, то сохранять это для истории смысла нет, указывает Чен.
В другом посте из своего блога Рэймонд объяснил механизмы утилит-просмотрщиков буфера обмена с синхронными обновлениями буфера. Здесь периодически выполняется опрос GetClipboardSequenceNumber. У данного подхода тоже есть проблемы: редкий опрос угрожает привести к пропуску изменения буфера, но слишком частые запросы создадут лишнюю нагрузку на систему.
Рэймонд обещает в следующий раз показать, как исправить код выше.
Читаемость Си-кода: грустный ликбез, чтобы жить стало веселее
Многие коллеги по цеху подтвердят, что читаемость кода на языке Си иногда оставляет желать лучшего. Как подтвердят и те, кто им плохо владеет, но так или иначе сталкивается в связи с рабочими задачами.
И всему виной (ожидаемо) выражения препроцессора и, как следствие, макросы. Да, вы правильно подумали. Именно те части кода, в которых вызываются такие легенды как:
Последние два очень легко спутать, если читать код невнимательно. Вместо них иногда рекомендуют использовать
#if defined // вместо #ifdef
#if !defined // вместо #ifndef
Но если же в компании/проекте/отделе нет определенного код-стайла, или он не предполагает написание длинного варианта, то, естественно, разрабы пишут короткую форму (я, честно признаться, тоже).
Чего далеко ходить - все open source проекты пестрят именно сокращенными вариантами этих выражений и с этим уже ничего не поделаешь.
А вот первое выражение из первой тройки игроков иногда вообще открывает врата ада, когда используется многострочный макрос с бэкслэш-символами (\) на концах строк.
Конечно же выражения препроцессора - это очень гибкий и полезный инструмент, позволяющий делать всё:
условную компиляцию;
выравнивание структур;
предотвращать повторные включения файла;
работать со строками;
грамотно оборачивать повторяющийся код и т.д. и т.п.
Но бывают случаи, когда упрощение кода с точки зрения алгоритма делает его слабо читаемым для того самого бедного программиста, пытающегося прочесть этот шедевр машинописного текста:
который определяется после объявления полей структуры.
Как обрабатывается аргумент x:
имя аргумента преобразуется в строку с помощью макроса "#x" и присваивается полю *name;
полю *value присваивается значение поля структуры b с названием аргумента x (тут нужно убедиться, что поле с именем x действительно существует в структуре b).
То есть чтобы при заполнении массива не писать каждый раз одинаковые строчки:
Ну и в самом конце вызываем удаление созданного макроса, чтобы оно не было использовано в коде в дальнейшем:
#undef _SPECIAL
Теперь после прочтения этого небольшого ликбеза вы можете смело пользоваться макросами и создавать более сложные и нечитаемые шедевры наконец-то разобрались в том, насколько гибкими могут оказаться выражения препроцессора ( вообще не понимаю, как вы жили без них раньше...)
Что такое быть Unix-программистом? Быть наполовину сисадмином (и вот почему)
Как вы поняли, этот пост на Хабре начался со смелого заявления. Конкретно в данном случае я не хотел бы раскладывать по полкам абсолютно все навыки, которые нужны Unix-программисту для успешной работы. Их можно получить простым запросом в поисковике или к любому чат-боту типа ChatGPT, DeepSeek и т.д. (на ваш вкус и цвет)
Я же отметил именно те, приобрести которые стоило мне многих набитых шишек. Они связаны с работой в проектах, состоящих из утилит, содержащих по несколько тысяч строк кода каждая.
Итак, навыки, правила, они же житейские мудрости, они же грабли, на которые наступал.
1. Сначала править конфиги и только потом - код. Это база
В течение практически двух лет такой работы, я часто сталкивался с ситуацией: когда возникает проблема, она находится (неожиданно) не в коде, а в конфигурации программы. Спустя десятки выполненных задач на стыке программирования и системного администрирования, я осознал одну очень важную вещь:
Сначала проверь конфигурацию и все её возможные варианты! Если все эти варианты исчерпаны, то только тогда, в последнюю очередь смотри в код!
Я очень долго привыкал к этой мысли, тратя тонны времени на чтение кода, так и не найдя там ошибки. А после приходил коллега-сисадмин, который пошарил конфигурацию, почитал документацию, поиграл с настройками и всё решил.
2. Владеть инструментами командной строки
Логично, но не очевидно на первый взгляд. В отличие от обычного программиста (в сферическом вакууме), когда ты можешь ограничиться пошаговой отладкой или логами, Unix-программист должен уметь работать с командной строкой. Хоть и не обязательно знать все команды и их опции "на зубок", но нужно понимать, для каких случаев какие утилиты полезны.
Сколько было случаев, когда работа над какой-то задачей ускорялась при использовании какой-нибудь утилиты, дающей больше информации об используемых ресурсах.
Например:
- при невозможности пошаговой отладки использовать perf, чтобы проанализировать стек вызовов
- уметь пользоваться grep'ом для поиска и выделения нужной информации из конкретных файлов
- использовать sed для формирования файлов без лишней информации (например в логах убирать строки с наличием отметок времени)
3. Уметь работать с виртуальными машинами, докером, анализаторами трафика
Например, не плодить виртуалки, а делать снэпшоты (вы скажете: "Спасибо, капитан-очевидность!", но я видел на своей практике тех, кто, не зная про снэпшоты, плодил виртуалки). Держать мастер-копии виртуалок с предварительно настроенной конфигурацией для быстрого развертывания новых машин. Понимать, для каких целей проще использовать докер-контейнер и т.д.
4. Работать с огромным количеством открытых одновременно утилит
Как ни странно, я встречал разработчиков, которые задавали вопрос: "Зачем так много всего?"
Ответ прост: когда непонятно поведение программы, нужно принимать во внимание всё.
Резюме: с таким набором навыков в какой-то момент начинаешь себя чувствовать, как оператор из Матрицы.
А какие особенности в Unix-разработке (и не только) подметили вы?
В YADRO есть команда, которая разрабатывает и отлаживает UEFI для самых разных продуктов компании. Подробнее о ней — в видеоролике → .
Первая особенность работы — в распределенной команде. Серверы, на которых инженеры разрабатывают прошивки, могут находиться в Москве, а разработчики — в других городах: от Владивостока до Калининграда и от Архангельска до Смоленска.
Системы, для которых разрабатывают прошивки в YADRO, делятся на два типа: с BMC и без него.
Больше о работе команды и, в целом, об истории BIOS/UEFI читайте в статье →
А если тоже хотите стать «поваром» UEFI, присмотритесь к одной из вакансий:
SystemVerilog отжил свое? На пятки наступает Scala/Chisel?
DARPA, управление перспективных исследовательских проектов Минобороны США, описывает Chisel как технологию, позволяющую маленьким командам создавать большие цифровые проекты. И я вполне могу с этим согласиться, но есть нюансы.
Chisel — это, по сути, библиотека Scala, а точнее, Domain Specific Language. Языку Scala уже больше 20 лет, он постоянно развивается, сочетает функциональное и императивное программирование. При написании кода на Scala вам доступны все библиотеки Java.
Scala — это масштабируемый язык, который позволяет добавлять свои языковые конструкции. На основе Scala можно создать язык под свои задачи. Так 12 лет назад и поступили инженеры в Беркли: выкинули из Verilog 90%, оставив только нужное, и обернули все это в Scala. Получился Chisel.
Chisel используют прежде всего для создания RTL-описаний. Также он позволяет проводить симуляцию несложных модулей. Это удобно для создания юнит-тестов и моделирования работы различных алгоритмов. В плане симуляции не стоит возлагать на Chisel такие же надежды, как на System C или что-то подобное. Симулировать вы сможете лишь очень маленькие схемки, а генерировать — хоть целые кластеры из тысяч процессоров, вообще все, что захотите.
На основе Chisel/Scala можно написать свой HLS-инструмент (High Level Synthesis), где одним росчерком пера вы будете создавать очень большие схемы, что с использованием одного Verilog невозможно.
В блоге YADRO Денис Муратов подробно сравнил Chisel/Scala с SystemVerilog в создании RTL-описаниях, раскрыл основные преимущества и недостатки альтернативы, а также ее дополнительные возможности — функциональное программирование и переиспользование модулей.
Я информирую о релизе постом только потому, что у меня лично сейчас нет свободного времени написать полноценную статью об всех изменениях. Изменений много.
Важное изменение, которое всё же я упомяну - появился свой backend для компилятора. То есть отказ от LLVM состоялся, но на данный момент только для Linux x86_64.
Системным программистам в YADRO нужно было «обмануть» драйвер в Linux: он не должен «знать», что работает в эмуляции.
Для этого ведущий инженер Никита приступил к созданию виртуального двойника Intel NTB Gen3 в QEMU, документации к которому в открытом доступе нет. Реализованная модель позволяет производить разработку и тестирование протоколов более высокого уровня, а также выполнять их качественное сравнение.
PCIe NTB не позволяет увидеть адресное пространство, которое принадлежит к подключенному по NTB соседнему устройству. Вкратце он работает так:
перенаправляет трафик PCIe между шинами как мост,
CPU рассматривает мост как конечное устройство,
CPU не «видит» все устройства на «другой» стороне, как правило, другая сторона — это другой компьютер.
Упрощенное представление PCIe NTB
С точки зрения эмуляции, нужно уделить особое внимание регистрам, прерываниям и моделированию поведения устройств.
В работе с PCI BAR необходимо обеспечить прозрачное использование Linux-драйвера Intel NTB для оптимального взаимодействия с оборудованием, которое мы эмулируем. Еще одна задача — разработать новые транспорты, которые работают поверх эмуляции: RPMSG, Virtio/Vhost, NTRDMA и другие. Также одна модель помогла найти ошибки в инициализации драйвера.
Никита подробно описывает тернистый путь создания виртуального двойника Intel NTB Gen3 в статье →
«Пушим байты» в сугробы: новогодняя демосцена 2025
Признанная классика демосцены — PICO-8, в арсенале которой сотни игр разной сложности. Мы же пойдем более оригинальным путем и напишем новогоднюю демку для BytePusher. Эта приставка включает 8-битный процессор, предлагает разрешение 256x256 и 8-битный цвет. Но самое интересное в ней — это OISC-архитектура ByteByeJump (BBJ).
OISC, One-Instruction Set Computer, известна гораздо меньше, чем RISC или CISC. Ее простота, очевидная из названия, привлекает немного энтузиастов, судя по странице BytePusher. Тем интересней будет сделать что-нибудь для нее с нуля.
Этим и занялся в своей статье Пётр Советов, специалист в области разработки DSL-компиляторов и старший научный сотрудник лаборатории специализированных вычислительных систем РТУ МИРЭА. Написал ассемблер на Python, разобрался с вычислениями без АЛУ и «отрисовал» классическое демо с падающим снегом. Еще и со «звездочкой» в виде сугробов и статичных цифр.
Три проверенных метода организовать обмен прерываниями между машинами QEMU c KVM и без
Эмулятор QEMU помогает решать ряд задач, в том числе разработку и отладку любого уровня коммуникаций. Вы можете эмулировать работу не только отдельной машины, но и связывать несколько независимых машин между собой.
Быстрая работа такой связки приятна при разработке/отладке и очень важна при массовом прогоне автотестов в CI. Как оптимизировать обмен прерываниями и какой подход к организации IQI вам подойдет — узнаете из статьи. А еще разберемся c:
устройством QEMU под капотом,
реализацией модели и драйвера,
добавлением прерываний MSI-X,
результатами замеров.
На бонус: десяток полезных материалов для изучения.
В гостях у подкаста «Битовые маски» — Николай Иготти, разработчик, участвовавший в создании многих известных проектов международных корпораций. Николай успел поработать над HotSpot в Sun Microsystems, над гипервизором VirtualBox, а также в разных проектах Google и EMC. Руководил разработкой Kotlin/Native компилятора и Compose Multiplatform в JetBrains, а сейчас трудится в Huawei. В выпуске затронули много разных тем — от гипервизоров до дизайна современных языков программирования:
Чем виртуальные машины отличаются друг от друга и от процессоров.
В чем сложности создания гипервизоров.
С какими проблемами придется столкнуться при создании нового языка программирования.
В чем особенности и отличия разработки системного ПО от прикладного.
Как связана разработка современных UI-фреймворков с системным программированием.
Какие задачи в системном программирование самые интересные.
Как учить будущих специалистов в этой сфере.
Бонус: разбор того, что не давало запустить VirtualBox c MacOS на архитектуре x86.
Добрый день. Пару месяцев назад я закончил написание книги и выставляю её в открытый доступ: GitHub
В чём идея? Контент этой книги представляет собой не только обучение языку C, но и обучение большому количеству прикладных вещей с серьёзной глубиной погружения. Я постарался дать ответ на как можно большее количество вопросов, которые возникают в процессе изучения, оставив минимальное количество дыр в понимании, как всё работает.
Посмотреть .html файл книги можно на GitHub-е. Но он не рендерит MathJax, поэтому лучше скачать файл c-book.html локально. Можно как угодно (в том числе в issues) сообщать мне о нерабочем коде в примерах, опечатках, неправильных утверждениях с моей стороны. Буду также рад увидеть конструктивную критику. Возможно, в ответ на неё, я буду добавлять новые главы в книгу.
(Эта книга абсолютно точно не является рекламой Zig-а.)
Если вы откроете проект на gitee.comвы увидите что проект включает в себя больше 700 (семисот!) репозиториев. Секрет в том что ни один из этих проектов в отдельном репозитории не компилируется независимо! Один знакомый разработчик, который работает с этим богатством, рассказал мне, что чтобы скомпилировать какой либо из проектов составляющих OpenHarmony вы должны скачать и скомпилировать минимум 450 репозиториев! Дело в том что даже отдельные приложения такие как mailBox, storage с СМС-ками, с контактами, видео плеер, ... которые, казалось бы, должны быть отдельными приложениями таковыми не являются. Они все компилируются как части одной монолитной прошивки смартфона (как части операционной системы) и вы не можете скомпилировать их без компиляции всей системы, такая опция просто не предусмотрена.
Поэтому OpenHarmony превратилась в огромного монстра который уже не может даже шевелиться от собственной тяжести. Внутренние связи и зависимости между функциями приложений и зависимостями ядра и системных библиотек никто не контролирует, они постоянно дублируются все в новых и новых модификациях, входят в противоречие друг другом, генерируют противоречивые потоки данных, копии данных, несовместимые интерфейсы, ... все это подобно раковой опухоли которая разъедает-разрывает носителя изнутри.
Каждый новый добавленный в OpenHarmony репозиторий приближает видимый крах проекта.
Интересно как обстоят дела у Андроида в этом смысле.
Вот мы (те кто следит за языком Zig) и дожили до этого момента. Большой вопрос зачем Zig в проде сейчас. Но сам факт такого похвальный. Начали появляться смельчаки, готовые взять ещё очень молодой язык в работу. Я туда не откликнусь, не мой стек. Но может найдутся желающие
Всем привет. Возможно, вы помните меня по статьям об изменениях в C++ и о фреймворке 🐙 userver, поэтому сразу к делу. 27 июля я выступаю на конференции C++ Zero Cost Conf, которая пройдёт в Москве и Ереване. Там я поделюсь новостями со встречи Международного комитета по стандартизации языка в Сент-Луисе и расскажу о наших планах на C++26 и C++29. А ещё отвечу на ваши вопросы. Приходите в гости!
Помимо меня, вас также будут ждать:
Константин Владимиров, руководитель отдела компиляторов и средств разработки Syntacore. Покажет развитие архитектуры сложного LLVM-based-C++-проекта и конкретные задачи, возникающие при его развитии.
Андрей Аксёнов, руководитель разработки инфраструктуры поиска Авито/Sphinx. Расскажет историю из продакшена с One Billion Row Challenge, парсингом гигабайтов TSV’шек, десятью странными оптимизациями и боттлнеками вообще везде.
Сергей Слотин, разработчик. Поговорит об устройстве памяти и кешей, их странностях и неожиданных последствиях для производительности.
Константин Облаков, старший разработчик браузера Яндекс Поиска и Рекламных технологий. Покажет на практике, как GDB позволяет добиться результатов, недоступных другими методами.
Полный список спикеров и темы докладов смотрите на сайте.
Если не получится прийти лично, подключайтесь дистанционно.