Я новичок в системном программировании Linux, и я столкнулся с API и ABI, читая системное программирование Linux .
Определение API:
API определяет интерфейсы, с помощью которых одна часть программного обеспечения взаимодействует с другой на уровне источника.
Определение ABI:
Принимая во внимание, что API определяет исходный интерфейс, ABI определяет низкоуровневый двоичный интерфейс между двумя или более частями программного обеспечения в конкретной архитектуре. Он определяет, как приложение взаимодействует с самим собой, как приложение взаимодействует с ядром и как приложение взаимодействует с библиотеками.
Как программа может общаться на уровне источника? Что такое уровень источника? Это связано с исходным кодом в любом случае? Или источник библиотеки включается в основную программу?
Единственное отличие, которое я знаю, это то, что API в основном используется программистами, а ABI - компилятором.
Ответы:
API - это то, что люди используют. Мы пишем исходный код. Когда мы пишем программу и хотим использовать библиотечную функцию, мы пишем такой код:
и нам нужно было знать, что существует метод
livenMyHills()
, который принимает длинный целочисленный параметр. Так что как интерфейс программирования все это выражается в исходном коде. Компилятор превращает это в исполняемые инструкции, которые соответствуют реализации этого языка в данной операционной системе. И в этом случае приводят к некоторым операциям низкого уровня на аудиоустройстве. Таким образом, определенные биты и байты выделяются на некотором оборудовании. Так что во время выполнения происходит множество действий на двоичном уровне, которые мы обычно не видим.источник
API: интерфейс прикладных программ
Это набор открытых типов / переменных / функций, которые вы выставляете из своего приложения / библиотеки.
В C / C ++ это то, что вы выставляете в заголовочных файлах, которые поставляются вместе с приложением.
ABI: двоичный интерфейс приложения
Вот как компилятор создает приложение.
Он определяет вещи (но не ограничивается ими):
источник
Я в основном сталкиваюсь с этими терминами в смысле API-несовместимых изменений или ABI-несовместимых изменений.
Изменение API, по сути, происходит там, где код, который был бы скомпилирован с предыдущей версией, больше не будет работать. Это может произойти, потому что вы добавили аргумент в функцию или изменили имя чего-то доступного за пределами вашего локального кода. Каждый раз, когда вы изменяете заголовок, и это заставляет вас что-то менять в файле .c / .cpp, вы вносите изменения в API.
Изменение ABI - это то, где код, который уже был скомпилирован для версии 1, больше не будет работать с версией 2 кодовой базы (обычно это библиотека). Как правило, сложнее отслеживать изменения, несовместимые с API, поскольку такая простая вещь, как добавление виртуального метода в класс, может быть несовместимой с ABI.
Я нашел два чрезвычайно полезных ресурса для выяснения, что такое совместимость с ABI и как ее сохранить:
источник
Это мои объяснения дилетанта:
include
файлах. Они предоставляют программные интерфейсы.источник
API-интерфейс совместно используемой библиотеки Linux с примером ABI
Этот ответ был извлечен из моего другого ответа: Что такое двоичный интерфейс приложения (ABI)? но я чувствовал, что это прямо отвечает и на этот вопрос, и что вопросы не являются дубликатами.
В контексте разделяемых библиотек наиболее важным следствием «наличия стабильного ABI» является то, что вам не нужно перекомпилировать свои программы после изменений библиотеки.
Как мы увидим в приведенном ниже примере, можно изменить ABI, нарушая работу программ, даже если API не изменился.
main.c
mylib.c
mylib.h
Компилируется и работает нормально с:
Теперь предположим, что для v2 библиотеки мы хотим добавить новое поле для
mylib_mystrict
вызываемогоnew_field
.Если мы добавили поле до того,
old_field
как в:и перестроить библиотеку, но нет
main.out
, тогда утверждение не удается!Это потому что строка:
сгенерировал сборку, которая пытается получить доступ к самой первой
int
структуре, которая теперьnew_field
вместо ожидаемойold_field
.Поэтому это изменение сломало ABI.
Если, однако, мы добавим
new_field
послеold_field
:тогда старая сгенерированная сборка все еще обращается к первой
int
структуре, и программа все еще работает, потому что мы сохранили ABI стабильным.Вот полностью автоматизированная версия этого примера на GitHub .
Еще один способ сохранить стабильность этого ABI состоял бы в том, чтобы рассматривать его
mylib_mystruct
как непрозрачную структуру и обращаться к ее полям только через помощников методов. Это облегчает поддержание стабильности ABI, но может повлечь за собой снижение производительности, поскольку мы выполняем больше вызовов функций.API против ABI
В предыдущем примере интересно отметить, что добавление
new_field
ранееold_field
только нарушало ABI, но не API.Это означает, что если бы мы перекомпилировали нашу
main.c
программу для библиотеки, она работала бы независимо.Однако мы бы также нарушили API, если бы изменили, например, сигнатуру функции:
так как в этом случае
main.c
перестанет компилироваться вообще.Семантический API против API программирования против ABI
Мы также можем классифицировать изменения API по третьему типу: семантические изменения.
Например, если мы изменили
чтобы:
тогда это не сломало бы ни API, ни ABI, но
main.c
все равно сломалось бы!Это потому, что мы изменили «человеческое описание» того, что должна делать функция, а не программно заметный аспект.
У меня только что было философское понимание, что формальная проверка программного обеспечения в некотором смысле перемещает больше «семантического API» в более «программно проверяемый API».
Семантический API против API программирования
Мы также можем классифицировать изменения API по третьему типу: семантические изменения.
Семантический API, как правило, представляет собой естественное описание того, что должен делать API, обычно включается в документацию API.
Поэтому возможно нарушить семантический API, не нарушая саму сборку программы.
Например, если мы изменили
чтобы:
тогда это не нарушило бы ни API программирования, ни ABI, но
main.c
семантический API сломался бы.Существует два способа программной проверки API контракта:
Протестировано в Ubuntu 18.10, GCC 8.2.0.
источник
( РИМЕНЕНИЕ В Инары я nterface) спецификацию для конкретной аппаратной платформы в сочетании с операционной системой. Это один шаг за пределы API ( РИМЕНЕНИЕ Р rogram Я nterface), который определяет вызовы от приложения к операционной системе. ABI определяет API плюс машинный язык для определенного семейства процессоров. API не гарантирует совместимость во время выполнения, но ABI делает, потому что он определяет машинный язык или формат времени исполнения.
учтивость
источник
Позвольте мне привести конкретный пример того, как ABI и API отличаются в Java.
ABI несовместимое изменение, если я изменю метод A # m () с принятия
String
в качестве аргументаString...
аргумента. Это не совместимо с ABI, потому что вы должны перекомпилировать код, который вызывает это, но это API-совместимый, поскольку вы можете решить его, перекомпилировав без каких-либо изменений кода в вызывающей стороне.Вот пример, изложенный. У меня есть библиотека Java с классом A
И у меня есть класс, который использует эту библиотеку
Теперь, автор библиотеки скомпилировал их класс A, я скомпилировал свой класс Main, и все это прекрасно работает. Представьте себе новую версию A
Если я просто возьму новый скомпилированный класс A и урону его вместе с ранее скомпилированным классом Main, я получу исключение при попытке вызвать метод
Если я перекомпилирую Main, это исправлено, и все снова работает.
источник
Ваша программа (исходный код) может быть скомпилирована с модулями, которые предоставляют надлежащий API .
Ваша программа (двоичная) может работать на платформах, которые обеспечивают надлежащий ABI .
API ограничивает определения типов, определения функций, макросы, иногда глобальные переменные, которые должна представлять библиотека.
ABI ограничивает то, что «платформа» должна предоставлять вашей программе для запуска. Мне нравится рассматривать это в 3 уровнях:
уровень процессора - набор инструкций, соглашение о вызовах
Уровень ядра - конвенция системного вызова конвенция специального пути к файлу (например,
/proc
и/sys
файлы в Linux) и т.д.Уровень ОС - формат объекта, библиотеки времени выполнения и т. Д.
Рассмотрим кросс-компилятор с именем
arm-linux-gnueabi-gcc
. «arm» обозначает архитектуру процессора, «linux» обозначает ядро, «gnu» указывает, что его целевые программы используют libc GNU в качестве библиотеки времени выполнения, в отличие отarm-linux-androideabi-gcc
используемой реализации libc в Android.источник
API
-Application Programming Interface
это интерфейс времени компиляции, который может использоваться разработчиком для использования не проектных функций, таких как библиотека, ОС, вызовы ядра в исходном кодеABI
[About] -Application Binary Interface
этоинтерфейс времени выполнения, который используется программой во время выполнения для связи между компонентами в машинном кодеисточник