Если ты программист на C/C++, то наверняка тебя на собеседовании спрашивали, или даже может быть ты спрашивал других - чем может быть плохо писать ядро ОС или ядерные модули на C++? Сегодня я хотел бы немного подискутировать на эту тему, особенно в свете новостей о выпуске Fuchsia OS на устройствах Google Nest Hub.
Всё началось в далёком 2016, когда на GitHub появился загадочный репозиторий, из кода которого следовало, что Google работает над разработкой новой ОС под названием Fuchsia. Впервые официально Google заговорил о Fuchsia на конференции Google I/O 2019, представив официальный сайт. Код отличался от Android и Chrome OS тем, что не был основан на ядре Linux, а на собственном ядре, которое сначала называлось Magenta, а потом Zircon. Ядро специально проектировалось, чтобы охватить весь спектр платформ, от встроенных RTOS систем, и мобильных платформ, до настольных ПК, тем самым порождало слухи о возможной замене в будущем Android и Chrome OS. Графический пользовательский интерфейс и приложения пишутся на фреймворке Flutter с использованием языка программирования Dart.
Ядро Zircon родилось из проекта ядра реального времени для встроенных устройств Little Kernel (LK). С одной стороны, Zircon можно назвать микроядерной архитектурой, в той степени, что там реализована концепция коммуникаций между компонентами, на основе отправки сообщений. С другой стороны, минималистическим ядро также сложно назвать, например, там реализовано более 170 системных вызовов, почти как в монолитном ядре. Что ещё примечательно, авторы черпали вдохновения из UNIX-систем, при этом концепцию сигналов они полностью игнорировали, но поддержали паттерн событийно-ориентированного программирования. Системные вызовы организованы таким образом, что не переводят процесс в сон, и вместо работы с файловыми дескрипторами, всё сводится к манипуляции с разными объектами.
Меня заинтересовало то, что ОС Fuchsia, и само ядро Zircon, почти полностью, написано на современном C++17, с ассемблерными вставками, когда надо работать напрямую с “железом”. Вообще, использование C++ для разработки встроенных систем и игр, не такая уж и редкость. Применяя C++ в таких ограниченных системах, приходится полностью отказываются от исключений, динамического определения и приведения типов, также часто нельзя позволить себе автоматическое динамическое выделение памяти, вместо этого пишутся вручную оптимизированные решения. Это похоже на то, с чем сталкиваются разработчики ОС Fuchsia, но последние пошли дальше и стали использовать C++ в коде ядра, если очень хочется, то можно. Для этого им пришлось составить список фич, которые нельзя использовать из C++, а также в режиме ядра полностью запретили использовать стандартную библиотеку из пространства std. Взамен, предлагается оптимизированная библиотека Fuchsia Base Library (FBL), которую можно использовать как в ядре, так и в пользовательском пространстве. Да, часть драйверов может работать в пользовательском пространстве, что немного снимает ограничения на использование библиотек, но это уже на усмотрение разработчика, например, код инициализации и чтения конфигурационных файлов выполняется не часто, поэтому можно позволить себе излишества.
Добавить немного герметика (Hermetic C++). Разработчики ОС Fuchsia приняли решение, использовать чистый C API, а не C++, внутри ядерных модулей, в системных вызовах, в динамически подгружаемых модулях ядра, во всех официально экспортируемых библиотечных API. Сделано это с целью предотвращения “съезжания” ABI, а также для возможности связки с другими языками (language binding), опять же с C++, или Dart/Go/Python/Rust.
Возвращаясь к вопросу на собеседовании, почему не пишут ядра на C++? Ой, я вас обманул, кажется, и не ответил напрямую. В качестве домашнего задания предлагаю подтянуть матчасть про API/ABI и ответить по списку, что вынудило разработчиков Fuchsia отказаться от следующих C++ фич?
Exceptions
RTTI and dynamic_cast
Operator overloading
Virtual inheritance
Statically constructed objects
Trailing return type syntax
Exception: when necessary for lambdas with otherwise unutterable return types
Initializer lists
thread_local in kernel code
masai
Если позанудствовать, то это не совсем так. Есть программы на C, которые невалидны в C++. Но с практической точки зрения да, это подмножество.
sergio_nsk
Вот сходу программа на C https://ideone.com/8Wsje5, которая не компилируется как C++ https://ideone.com/FNr9e9. Это совершенно разные языки программирования с наследованием удачного синтаксиса С. Никто же не употребляет C/Java. Точно так же не надо писать C/C++.
Woodroof
А причём тут C/Java? Эти-то языки сильно различаются, а в примере выше если убрать неиспользуемое, то останется валидная программа на C++.
Tuxman Автор
Несколько человек указали на неточность и я убрал это из текста.
Я поверил книжке от 2012 года Object Oriented Programming with C++, Second Edition by Richard Johnsonbaugh
Сейчас я нашёл интересную статью с примерами C++ is not a superset of C.
SinsI
C++ — это надмножество некоторой старой версии C.
Не все дальнейшие нововведения C были приняты для C++.
Woodroof
Это тоже неверно. С самого начала были несовместимости, например, не поддержан int по умолчанию.
Ну а самые вкусные вещи из новых стандартов C в новые стандарты C++ вошли.