Введение

Обзор и сравнение API ядра Linux и ABI. Ядро Linux предоставляет несколько интерфейсов для пользовательского пространства и кода режима ядра, которые используются для различных целей и имеют различные свойства по дизайну. В ядре Linux существует два типа интерфейса прикладного программирования (API): API "kerneluser space" и API "kernel internal".

API для Linux

API Linux включает в себя API ядра и пользовательского пространства, который позволяет коду в пользовательском пространстве получать доступ к системным ресурсам и службам ядра Linux. Он состоит из интерфейса системных вызовов ядра Linux и подпрограмм в стандартной библиотеке C. Основной целью разработки API Linux было предоставление полезных функций, определенных в спецификациях POSIX, в разумно совместимом, надежном и производительном виде, а также предоставление дополнительных полезных функций, не определенных в POSIX, как это делают API ядра и пользовательского пространства других систем, реализующих API POSIX. API Linux намеренно сохранял стабильность на протяжении десятилетий благодаря политике исключения ломающих изменений; эта стабильность гарантирует переносимость исходного кода. В то же время разработчики ядра Linux исторически проявляли консерватизм и скрупулезность при добавлении новых системных вызовов. Значительная часть доступного свободного и открытого программного обеспечения написана для API POSIX. Поскольку разработка в большей степени направлена на ядро Linux, чем на другие POSIX-совместимые комбинации ядра и стандартной библиотеки C, ядро Linux и его API были дополнены дополнительными функциями. Программирование для полного API Linux, а не только для API POSIX, может дать преимущества в тех случаях, когда эти дополнительные функции полезны. Хорошо известные современные примеры – udev, systemd и Weston. Такие люди, как Леннарт Поеттеринг, открыто выступают за предпочтение API Linux перед API POSIX, когда это дает преимущества. На FOSDEM 2016 Майкл Керриск описал некоторые проблемы, связанные с API пользовательского пространства ядра Linux, указав на наличие в нем множества ошибок проектирования, таких как нерасширяемость, сложность поддержки, чрезмерная сложность, ограниченная функциональность, нарушение стандартов и непоследовательность. Большинство этих ошибок невозможно исправить, поскольку это привело бы к нарушению ABI, предоставляемого ядром пользовательскому пространству.

Интерфейс системных вызовов ядра Linux

Интерфейс системных вызовов ядра — это совокупность всех реализованных и доступных системных вызовов в ядре. В ядре Linux различные подсистемы, такие как Direct Rendering Manager (DRM), определяют собственные системные вызовы, которые все вместе составляют интерфейс системных вызовов. Различные проблемы, связанные с организацией системных вызовов ядра Linux, активно обсуждаются в сообществе. На эти проблемы указывали Энди Лутомирски, Майкл Керриск и другие.

Linux ABI (англ.) русск.

Термин Linux ABI относится к ABI ядра и пользовательского пространства. Бинарный интерфейс приложения (ABI) относится к скомпилированным двоичным файлам, представленным в машинном коде. Любой такой ABI, следовательно, привязан к набору инструкций. Определение полезного ABI и поддержание его стабильности – это не столько ответственность разработчиков ядра Linux или разработчиков библиотеки GNU C, сколько задача дистрибутивов Linux и независимых поставщиков программного обеспечения (ISV), которые хотят продавать и предоставлять поддержку своего проприетарного программного обеспечения исключительно в виде двоичных файлов для конкретного Linux ABI, а не поддерживать несколько Linux ABI. ABI должен быть определен для каждого набора инструкций, таких как x86, x86-64, MIPS, ARMv7-A (32 бит), ARMv8-A (64 бит) и т.д., с указанием порядка байтов (endianness), если оба варианта поддерживаются. Должна быть возможность компилировать программное обеспечение с использованием различных компиляторов в соответствии с определениями, указанными в ABI, и достичь полной бинарной совместимости. Примерами компиляторов, являющихся свободным и открытым программным обеспечением, служат GNU Compiler Collection и LLVM/Clang.

Встроенные в ядро API

Существует множество внутренних API ядра, позволяющих подсистемам ядра взаимодействовать друг с другом. Они поддерживаются в относительно стабильном состоянии, однако стабильность не гарантируется. Внутренний API ядра может быть изменен, если это обосновано новыми исследованиями или пониманием; все необходимые изменения и тестирование должны быть выполнены автором. Ядро Linux является монолитным, следовательно, драйверы устройств являются компонентами ядра. Чтобы облегчить задачу компаниям, поддерживающим свои (проприетарные) драйверы устройств вне основного дерева ядра, неоднократно поступали запросы на предоставление стабильных API для драйверов устройств. Разработчики ядра Linux неоднократно отказывались гарантировать стабильность внутренних API ядра для драйверов устройств. Такая гарантия замедлила бы развитие ядра Linux в прошлом и продолжает замедлять его в будущем, а также не требуется в силу природы свободного и открытого программного обеспечения. Таким образом, ядро Linux сознательно не имеет стабильного внутреннего API.

Внутриядерные АБИ

Поскольку в ядре нет стабильных API, не может быть и стабильных ABI.

Абстракционные API

Для многих сценариев использования API Linux считается слишком низкоуровневым, поэтому необходимо использовать API более высокого уровня абстракции. API более высокого уровня реализуются на основе низкоуровневых API. Примеры:

Реализация спецификаций OpenGL и Vulkan в проприетарных графических драйверах Linux и реализация с открытым исходным кодом в Mesa. Реализация спецификации OpenAL. Simple DirectMedia Layer: API абстракции для ввода/звука/и т.д., доступный для многих операционных систем. Simple and Fast Multimedia Library: аналогично вышеуказанному.