Je suis nouveau dans la programmation système Linux et je suis tombé sur l'API et l'ABI en lisant la programmation système Linux .
Définition de l'API:
Une API définit les interfaces par lesquelles un logiciel communique avec un autre au niveau source.
Définition de l'ABI:
Alors qu'une API définit une interface source, une ABI définit l'interface binaire de bas niveau entre deux ou plusieurs logiciels sur une architecture particulière. Il définit comment une application interagit avec elle-même, comment une application interagit avec le noyau et comment une application interagit avec les bibliothèques.
Comment un programme peut-il communiquer au niveau de la source? Qu'est-ce qu'un niveau source? Est-ce lié au code source de toute façon? Ou la source de la bibliothèque est-elle incluse dans le programme principal?
La seule différence que je connais est que l'API est principalement utilisée par les programmeurs et ABI est principalement utilisée par le compilateur.
Réponses:
L'API est ce que les humains utilisent. Nous écrivons du code source. Lorsque nous écrivons un programme et que nous voulons utiliser une fonction de bibliothèque, nous écrivons du code comme:
et nous avions besoin de savoir qu'il existe une méthode
livenMyHills()
, qui prend un long paramètre entier. Donc, en tant qu'interface de programmation, tout est exprimé en code source. Le compilateur transforme cela en instructions exécutables conformes à l'implémentation de ce langage sur ce système d'exploitation particulier. Et dans ce cas, il en résulte des opérations de bas niveau sur une unité audio. Ainsi, des bits et des octets particuliers sont éjectés sur certains matériels. Donc, au moment de l'exécution, il y a beaucoup d'actions au niveau binaire que nous ne voyons généralement pas.la source
API: interface de programme d'application
Il s'agit de l'ensemble des types / variables / fonctions publics que vous exposez à partir de votre application / bibliothèque.
En C / C ++, c'est ce que vous exposez dans les fichiers d'en-tête que vous livrez avec l'application.
ABI: interface binaire d'application
C'est ainsi que le compilateur crée une application.
Il définit les choses (mais n'est pas limité à):
la source
Je rencontre principalement ces termes dans le sens d'un changement incompatible avec l'API ou d'un changement incompatible avec l'ABI.
Un changement d'API est essentiellement l'endroit où le code qui aurait été compilé avec la version précédente ne fonctionnera plus. Cela peut se produire parce que vous avez ajouté un argument à une fonction ou changé le nom d'un élément accessible en dehors de votre code local. Chaque fois que vous modifiez un en-tête et que cela vous oblige à modifier quelque chose dans un fichier .c / .cpp, vous avez effectué une modification d'API.
Un changement ABI est l'endroit où le code qui a déjà été compilé avec la version 1 ne fonctionnera plus avec la version 2 d'une base de code (généralement une bibliothèque). C'est généralement plus difficile à suivre que les changements incompatibles avec l'API car quelque chose d'aussi simple que l'ajout d'une méthode virtuelle à une classe peut être incompatible avec l'ABI.
J'ai trouvé deux ressources extrêmement utiles pour déterminer ce qu'est la compatibilité ABI et comment la préserver:
la source
Voici mes explications profanes:
include
fichiers. Ils fournissent des interfaces de programmation.la source
Exemple d'API exécutable minimale de bibliothèque partagée Linux vs ABI
Cette réponse a été extraite de mon autre réponse: Qu'est-ce qu'une interface binaire d'application (ABI)? mais j'ai senti que cela répond directement à celle-ci aussi, et que les questions ne sont pas des doublons.
Dans le contexte des bibliothèques partagées, l'implication la plus importante d '"avoir un ABI stable" est que vous n'avez pas besoin de recompiler vos programmes après les changements de bibliothèque.
Comme nous le verrons dans l'exemple ci-dessous, il est possible de modifier l'ABI, interrompant les programmes, même si l'API est inchangée.
principal c
mylib.c
mylib.h
Compile et fonctionne correctement avec:
Maintenant, supposons que pour la v2 de la bibliothèque, nous souhaitons ajouter un nouveau champ à
mylib_mystrict
appelénew_field
.Si nous avons ajouté le champ avant
old_field
comme dans:et reconstruit la bibliothèque mais pas
main.out
, alors l'assertion échoue!C'est parce que la ligne:
avait généré l'assembly qui tente d'accéder au tout premier
int
de la structure, qui est maintenantnew_field
au lieu de l'attenduold_field
.Par conséquent, ce changement a cassé l'ABI.
Si, cependant, nous ajoutons
new_field
aprèsold_field
:alors l'ancien assembly généré accède toujours au premier
int
de la structure, et le programme fonctionne toujours, car nous avons maintenu l'ABI stable.Voici une version entièrement automatisée de cet exemple sur GitHub .
Une autre façon de maintenir cette ABI stable aurait été de la traiter
mylib_mystruct
comme une structure opaque et d'accéder uniquement à ses champs via des assistants de méthode. Cela facilite le maintien de la stabilité de l'ABI, mais entraînerait une surcharge de performance car nous ferions plus d'appels de fonctions.API vs ABI
Dans l'exemple précédent, il est intéressant de noter que l'ajout de l'
new_field
avantold_field
, n'a cassé que l'ABI, mais pas l'API.Ce que cela signifie, c'est que si nous avions recompilé notre
main.c
programme contre la bibliothèque, cela aurait fonctionné de toute façon.Nous aurions également cassé l'API si nous avions changé par exemple la signature de la fonction:
car dans ce cas,
main.c
arrêterait complètement la compilation.API sémantique vs API de programmation vs ABI
Nous pouvons également classer les changements d'API dans un troisième type: les changements sémantiques.
Par exemple, si nous avions modifié
à:
alors cela n'aurait cassé ni l'API ni l'ABI, mais
main.c
le casserait quand même!Ceci est dû au fait que nous avons changé la "description humaine" de ce que la fonction est censée faire plutôt qu'un aspect perceptible par programme.
J'ai juste eu la perspicacité philosophique que la vérification formelle du logiciel dans un sens déplace plus de «l'API sémantique» vers une «API plus vérifiable par programme».
API sémantique vs API de programmation
Nous pouvons également classer les changements d'API dans un troisième type: les changements sémantiques.
L'API sémantique est généralement une description en langage naturel de ce que l'API est censée faire, généralement incluse dans la documentation de l'API.
Il est donc possible de casser l'API sémantique sans casser la construction du programme lui-même.
Par exemple, si nous avions modifié
à:
alors cela n'aurait cassé ni l'API de programmation, ni l'ABI, mais
main.c
l'API sémantique serait cassée .Il existe deux façons de vérifier par programme l'API du contrat:
Testé dans Ubuntu 18.10, GCC 8.2.0.
la source
( A pplication B inaire I nterface) Une spécification pour une plate - forme matérielle spécifique combiné avec le système d'exploitation. Il est une étape au - delà de l'API ( A pplication P rogramme I nterface), qui définit les appels provenant de l'application au système d'exploitation. L'ABI définit l'API ainsi que le langage machine pour une famille de CPU particulière. Une API n'assure pas la compatibilité d'exécution, mais une ABI le fait, car elle définit le format du langage machine, ou du format d'exécution.
Courtoisie
la source
Permettez-moi de donner un exemple spécifique de la différence entre ABI et API en Java.
Un changement incompatible ABI est si je change une méthode A # m () de prendre a
String
comme argument enString...
argument. Ce n'est pas compatible ABI car vous devez recompiler le code qui appelle cela, mais il est compatible avec l'API car vous pouvez le résoudre en recompilant sans aucune modification de code dans l'appelant.Voici l'exemple énoncé. J'ai ma bibliothèque Java avec la classe A
Et j'ai une classe qui utilise cette bibliothèque
Maintenant, l'auteur de la bibliothèque a compilé sa classe A, j'ai compilé ma classe Main et tout fonctionne bien. Imaginez qu'une nouvelle version de A arrive
Si je prends simplement la nouvelle classe compilée A et la dépose avec la classe Main précédemment compilée, j'obtiens une exception en tentant d'appeler la méthode
Si je recompile Main, cela est corrigé et tout fonctionne à nouveau.
la source
Votre programme (code source) peut être compilé avec des modules qui fournissent une API appropriée .
Votre programme (binaire) peut fonctionner sur des plates-formes qui fournissent un ABI approprié .
L'API restreint les définitions de type, les définitions de fonction, les macros, parfois les variables globales qu'une bibliothèque doit exposer.
ABI restreint ce qu'une «plate-forme» doit fournir pour que votre programme s'exécute. J'aime le considérer en 3 niveaux:
niveau du processeur - le jeu d'instructions, la convention d'appel
niveau du noyau - la convention d'appel système, la convention spéciale de chemin de fichier (par exemple les fichiers
/proc
et/sys
sous Linux), etc.Niveau du système d'exploitation - le format de l'objet, les bibliothèques d'exécution, etc.
Considérez un compilateur croisé nommé
arm-linux-gnueabi-gcc
. "arm" indique l'architecture du processeur, "linux" indique le noyau, "gnu" indique que ses programmes cibles utilisent la libc de GNU comme bibliothèque d'exécution, différente dearm-linux-androideabi-gcc
celle utilisée par l'implémentation libc d'Android.la source
API
-Application Programming Interface
est une interface de compilation qui peut être utilisée par le développeur pour utiliser des fonctionnalités non liées au projet telles que la bibliothèque, le système d'exploitation, les appels de base dans le code sourceABI
[About] -Application Binary Interface
est uneinterface d' exécution qui est utilisée par un programme pendant l'exécution pour la communication entre les composants dans le code machinela source