Qu'est-ce qu'une interface binaire d'application (ABI)?

Je n'ai jamais compris ce qu'est un ABI. S'il vous plaît, ne me montrez pas un article de Wikipédia. Si je pouvais le comprendre, Je ne serais pas ici à poster un poste aussi long.

C'est mon état d'esprit sur les différentes interfaces:

une télécommande TV est une interface entre l'utilisateur et le téléviseur. C'est une entité existante, mais inutile (ne fournit aucune fonctionnalité) par elle-même. Toutes les fonctionnalités de chacun de ces boutons sur la télécommande est mise en oeuvre dans le téléviseur.

de l'Interface: C'est une "entité existante" couche entre le functionality et consumer dont fonctionnalité. Une interface toute seule est ne rien faire. Il vient de invoque la fonctionnalité se trouvant derrière.

maintenant selon qui l'utilisateur est là sont différents types d'interfaces.

Ligne De Commande Les commandes Interface (CLI) sont les entités existantes, le consommateur est l'utilisateur et la fonctionnalité qui se cache derrière.

functionality: mon logiciel la fonctionnalité qui résout certains but pour lequel nous sommes décrivant cette interface.

existing entities: commandes

consumer: utilisateur

interface utilisateur graphique(GUI) fenêtre, boutons, etc. être l'existant entités, et encore une fois le consommateur est l'utilisateur et la fonctionnalité se trouve derrière.

functionality: mon logiciel la fonctionnalité qui résout certains but pour lequel nous sommes décrivant cette interface.

existing entities: fenêtre, boutons etc..

consumer: utilisateur

Application Programming Interface(API) de plus correct, interfaces (en la programmation basée sur l'interfaçage) sont les entités existantes, le consommateur ici est un autre programme pas un utilisateur, et encore la fonctionnalité se trouve derrière cette couche.

functionality: mon logiciel la fonctionnalité qui résout certains but pour lequel nous sommes décrivant cette interface.

existing entities: fonctions, Interfaces(tableau de fonctions).

consumer: un autre programme/de l'application.

Application binaire Interface (ABI) voici où mon problème commence.

functionality: ???

existing entities: ???

consumer: ???

  • j'ai écrit des logiciels dans différentes langues et fourni différents types d'interfaces (CLI, GUI, et API), mais je ne suis pas sûr, si je jamais, fourni un ABI.

Wikipédia dit:

ABIs détails de la couverture comme

  • type de données, taille et alignement;
  • la convention d'appel, qui contrôle comment les arguments des fonctions sont passé et des valeurs de retour (extrait;
  • les numéros d'appel système et comment une application devrait faire des appels système à l'exploitation système;

autres ABIs normaliser les détails tels que

  • the C++ name mangling,
  • exception propagation, et
  • appelant convention entre compilateurs sur la même plate-forme, mais ne ne nécessite pas de plateforme croisée compatibilité.
  • qui a besoin de ces détails? S'il vous plaît ne pas dire le système d'exploitation. Je sais assemblage de programmation. Je sais comment relier et charger fonctionne. Je sais exactement ce qui se passe à l'intérieur.

  • pourquoi le nom c++ mangling est entré? Je croyais qu'on parlait au niveau binaire. Pourquoi les langues?

quoi qu'il en soit, j'ai téléchargé le [PDF] System V Application Binary Interface édition 4.1 (1997-03-18) pour voir ce qu'il contenir. Eh bien, elle n'a pas de sens.

  • pourquoi contient-il deux chapitres (4e et 5e) pour décrire le format de fichier ELF ? En fait, ce sont les deux seuls chapitres importants de cette spécification. Les autres chapitres sont "spécifiques au processeur". De toute façon, j'ai pensé que c'est un sujet complètement différent. S'il vous plaît ne dites pas que les spécifications de format de fichier ELF sont L'ABI. Il n'est pas admissible à titre d'interface 15191110920 "selon la définition.

  • je sais, puisque nous parlons à un niveau si bas, il doit être très spécifique. Mais je ne suis pas sûr que ce soit spécifique à l ' "instruction set architecture (ISA)"?

  • Où puis-je trouver Microsoft Windows' ABI?

ainsi, ce sont les principales requêtes qui sont écoute-moi.

331
demandé sur Peter Mortensen 2010-01-31 12:30:24

14 réponses

une façon facile de comprendre" ABI "est de le comparer à"API".

vous connaissez déjà le concept D'API. Si vous souhaitez utiliser les fonctionnalités d'une bibliothèque ou de votre système D'exploitation, vous utiliserez une API. L'API se compose de types de données/structures, constantes, fonctions, etc. que vous pouvez utiliser dans votre code pour accéder à la fonctionnalité de ce composant externe.

un ABI est très similaire. Pensez-y comme la version compilée d'une API (ou en tant QU'API au niveau du langage machine). Lorsque vous écrivez du code source, vous accédez à la bibliothèque via une API. Une fois le code compilé, votre application accède aux données binaires de la bibliothèque via L'ABI. L'ABI définit les structures et les méthodes que votre application compilée utilisera pour accéder à la bibliothèque externe (comme L'API l'a fait), seulement à un niveau inférieur.

ABIs sont importants quand il s'agit d'applications qui utilisent des bibliothèques externes. Si un programme est construit pour utiliser une bibliothèque particulière et cette bibliothèque est mise à jour plus tard, vous ne voulez pas avoir à recompiler cette application (et du point de vue de l'utilisateur final, vous ne pouvez pas avoir la source). Si la bibliothèque mise à jour utilise le même ABI, alors votre programme n'aura pas besoin de changer. L'interface de la bibliothèque (qui est tout ce dont votre programme se soucie vraiment) est la même, même si le fonctionnement interne peut avoir changé. Deux versions d'une bibliothèque qui ont le même ABI sont parfois appelées "compatible binaire" puisqu'ils ont la même interface de bas niveau (vous devriez pouvoir remplacer l'ancienne version par la nouvelle et ne pas avoir de problèmes majeurs).

parfois, les changements ABI sont inévitables. Lorsque cela se produit, tous les programmes qui utilisent cette bibliothèque ne fonctionneront pas à moins qu'ils ne soient compilés de nouveau pour utiliser la nouvelle version de la bibliothèque. Si L'ABI change mais que l'API ne change pas, alors les anciennes et les nouvelles versions de la bibliothèque sont parfois appelées "compatibles avec les sources". Ce implique que bien qu'un programme compilé pour une version de bibliothèque ne fonctionnera pas avec l'autre, le code source écrit pour l'un fonctionnera pour l'autre s'il est recompilé.

pour cette raison, les rédacteurs de bibliothèque ont tendance à essayer de garder leur ABI stable (pour minimiser les perturbations). Maintenir un ABI stable signifie Ne pas changer les interfaces de fonction (retourner le type et le nombre, les types et l'ordre des arguments), les définitions des types de données ou des structures de données, les constantes définies, etc. Nouvelles fonctions et données les types peuvent être ajoutés, mais celles existantes doit rester le même. Si vous développez, disons, un champ de structure de données de 16 bits en un champ de 32 bits, alors le code déjà compilé qui utilise cette structure de données n'accédera pas à ce champ (ou à tout autre qui le suit) correctement. L'accès aux membres de la structure de données est converti en adresses mémoire et offsets pendant la compilation et si la structure de données change, alors ces offsets ne pointent pas vers ce que le code attend d'eux et les résultats sont imprévisible, au mieux.

un ABI n'est pas nécessairement quelque chose que vous fournirez explicitement à moins que vous vous attendiez à ce que les gens interagissent avec votre code en utilisant assembly. Il n'est pas non plus spécifique à la langue, puisque (par exemple) une application C et une application Pascal utiliseront le même ABI après avoir été compilées.

Edit: Concernant votre question sur les chapitres concernant l'ELFE format de fichier dans le SysV ABI docs: L' la raison pour laquelle ces informations sont incluses est que le format ELF définit l'interface entre le système d'exploitation et l'application. Quand vous dites au système D'exploitation d'exécuter un programme, il s'attend à ce que le programme soit formaté d'une certaine manière et (par exemple) s'attend à ce que la première section du binaire soit un en-tête ELF contenant certaines informations à des décalages mémoire spécifiques. C'est ainsi que l'application communique des informations importantes sur elle-même au système d'exploitation. Si vous construisez un programme dans un non-ELF format binaire(tel que A. out ou PE), puis un OS qui attend des applications formatées par ELF ne sera pas en mesure d'interpréter le fichier binaire ou exécuter l'application. C'est une des principales raisons pour lesquelles les applications Windows ne peuvent pas être exécutées directement sur une machine Linux (ou vice versa) sans être soit recompilées, soit exécutées à l'intérieur d'une couche d'émulation qui peut traduire d'un format binaire à un autre.

IIRC, Windows utilise actuellement le exécutable Portable (ou PE) format. Il y a des liens dans la section "Liens externes" de cette page Wikipédia avec plus d'informations sur le format PE.

aussi, en ce qui concerne votre note sur le manglage de nom C++: L'ABI peut définir une façon" standardisée " pour un compilateur C++ de faire le manglage de nom à des fins de compatibilité. Qui est, si je créer une bibliothèque et d'élaborer un programme qui utilise la bibliothèque, vous devriez être en mesure d'utiliser un autre compilateur que j'ai fait et ne pas avoir à vous soucier de la binaires incompatibles en raison des différentes name mangling régimes. Ceci n'est vraiment utile que si vous définissez un nouveau format de fichier binaire ou que vous écrivez un compilateur ou un éditeur de liens.

362
répondu bta 2018-07-05 14:42:26

si vous savez assembler et comment les choses fonctionnent au niveau OS, vous êtes conforme à un certain ABI. L'ABI régit des choses comme la façon dont les paramètres sont passés, où les valeurs de retour sont placées. Pour de nombreuses plateformes, il n'y a qu'un seul ABI à choisir, et dans ces cas, L'ABI est simplement "comment les choses fonctionnent".

cependant, L'ABI régit aussi des choses comme la façon dont les classes/objets sont disposés en C++. Cela est nécessaire si vous voulez être en mesure de passer des références d'objet à travers le module limites ou si vous voulez mélanger le code compilé avec différents compilateurs.

aussi, si vous avez un système d'exploitation 64 bits qui peut exécuter des binaires 32 bits, vous aurez des Abi différents pour le code 32 et 64 bits.

en général, tout code que vous liez dans le même exécutable doit être conforme au même ABI. Si vous voulez communiquer entre les codes en utilisant différents ABIs, vous devez utiliser une certaine forme de RPC ou de protocoles de sérialisation.

je pense que vous êtes essayer trop fort d'intégrer différents types d'interfaces dans un ensemble fixe de caractéristiques. Par exemple, une interface ne doit pas nécessairement être divisée entre les consommateurs et les producteurs. Une interface est juste une convention par laquelle deux entités interagissent.

ABIs peut être (partiellement) ISA-agnostique. Certains aspects (comme les conventions d'appel) dépendent de L'ISA, tandis que d'autres aspects (comme la mise en page de Classe C++) ne dépendent pas de L'ISA.

un ABI bien défini est très important pour les gens qui écrivent des compilateurs. Sans un ABI bien défini, il serait impossible de générer du code interopérable.

modifier: quelques notes pour clarifier:

  • "Binaire" ABI n'exclut pas l'utilisation de cordes ou de texte. Si vous voulez lier une DLL exportant une Classe C++, Les méthodes et les signatures de type doivent être encodées quelque part. C'est là qu'intervient la modification de nom en C++.
  • La raison pour laquelle vous n'avez jamais fourni l'ABI est que la grande majorité des programmeurs ne le ferai jamais. Les abi sont fournis par les mêmes personnes qui conçoivent la plate-forme (c'est-à-dire le système d'exploitation), et très peu de programmeurs auront le privilège de concevoir un ABI largement utilisé.
97
répondu JesperE 2010-02-27 15:11:18

une interface binaire d'application (ABI) est similaire à une API, mais la fonction n'est pas accessible à l'appelant au niveau du code source. Seule une représentation binaire est accessible/disponible.

ABIs peut être défini au niveau du processeur de l'architecture au niveau ou au niveau de l'OS. Les Abi sont des standards qui doivent être suivis par la phase de génération de code du compilateur. Le standard est fixé soit par L'OS, soit par le processeur.

fonctionnalité: définir la mécanisme / standard pour rendre les appels de fonction indépendants du langage de mise en œuvre ou d'un compilateur/linker/chaîne d'outils spécifique. Fournir le mécanisme qui permet JNI, ou une interface Python-C, etc.

entités existantes: fonctions sous forme de code machine.

consommateur: une autre fonction (y compris une dans une autre langue, compilée par un autre compilateur, ou liée par un autre linker).

16
répondu alvin 2017-09-15 23:31:42

Vous fait ne pas besoin d'un ABI si--

  • votre programme n'a pas de fonctions, et --
  • votre programme est un exécutable unique qui tourne seul (c.-à-d. un système intégré) où il est littéralement la seule chose qui tourne et il n'a pas besoin de parler à quoi que ce soit d'autre.

Un résumé simpliste:

API: " voici toutes les fonctions que vous pouvez appeler."

ABI: " C'est comment appeler une fonction."

L'ABI est un ensemble de règles que les compilateurs et les linkers respecter pour compiler votre programme afin de fonctionner correctement. Les abi couvrent plusieurs sujets:

  • La partie la plus importante et la plus importante d'un ABI est sans doute la "norme d'appel de procédure 1519360920 parfois appelée" Convention d'appel". Les conventions d'appel standardisent la façon dont les" fonctions " sont traduites en code d'assemblage.
  • ABIs dicte également la façon dont les noms des fonctions exposées dans les bibliothèques devraient être représentés afin que d'autres codes puissent appeler ces bibliothèques et savoir quels arguments devraient être passés. Ceci est appelé "nom de mangle."
  • Les ABIs
  • dictent également le type de types de données qui peuvent être utilisés, la façon dont ils doivent être alignés et d'autres détails de faible niveau.

je regarde de plus près la Convention d'appel, que je considère comme le cœur d'une ABI:

La machine elle-même n'a pas de notion de "fonctions". Lorsque vous écrivez une fonction dans un langage de haut niveau comme c, le compilateur génère une ligne de code d'assemblage comme _MyFunction1: . C'est un étiquette , qui sera éventuellement résolu dans une adresse par l'assembleur. Cette étiquette marque le" début "de votre" fonction " dans le code d'assemblage. Dans le code de haut niveau, quand vous " appelez "cette fonction, ce que vous faites vraiment est de provoquer le CPU à sauter à l'adresse de cette étiquette et continuer l'exécution là.

En préparation pour le saut, le compilateur doit faire un tas de choses importantes. La Convention d'appel est comme une liste de contrôle que le compilateur suit pour faire toutes ces choses:

  • tout d'abord, le compilateur insère un peu de code d'assemblage pour enregistrer l'adresse courante, de sorte que lorsque votre" fonction " est terminée, le CPU peut revenir au bon endroit et continuer l'exécution.
  • ensuite, le compilateur génère le code d'assemblage pour passer les arguments.
    • certaines conventions d'appel dictent que les arguments doivent être mis sur la pile ( dans un ordre particulier , bien entendu).
    • D'autres conventions dictent que les arguments doivent être mis dans des registres particuliers ( en fonction de leurs types de données bien sûr).
    • d'autres conventions encore prescrivent qu'une combinaison spécifique de pile et de registres doit être utilisée.
  • bien sûr, s'il y avait quelque chose d'important dans ces registres avant, ces valeurs sont maintenant réécrit et perdu pour toujours, de sorte que certaines conventions d'appel peuvent dicter que le compilateur devrait sauvegarder certains de ces registres avant d'y mettre les arguments.
  • maintenant le compilateur insère une instruction de saut disant au CPU d'aller à cette étiquette qu'il a fait auparavant ( _MyFunction1: ). À ce stade, vous pouvez considérer que le CPU est "dans" votre "fonction".
  • à la fin de la fonction, le compilateur met du code d'assemblage qui fera écrire le CPU retourner la valeur au bon endroit. La convention d'appel détermine si la valeur de retour doit être mis dans un registre particulier (selon son type), ou sur la pile.
  • c'est l'heure du nettoyage. La convention d'appel dictera où le compilateur place le code d'assemblage de nettoyage.
    • certaines conventions disent que l'appelant doit nettoyer la pile. Cela signifie qu'après la" fonction " est fait et le CPU saute de nouveau à l'endroit où il était avant, le code suivant à exécuter devrait être un code de nettoyage très spécifique.
    • D'autres conventions disent que les parties particulières du code de nettoyage devraient être à la fin de la" fonction " avant le saut en arrière.

il existe de nombreuses conventions ABIs / calling. Les principales sont:

  • pour le CPU x86 ou x86-64 (32 bits environnement):
    • CDECL
    • STDCALL
    • FASTCALL
    • VECTORCALL
    • THISCALL
  • pour le CPU x86-64 (environnement 64 bits)):
    • SYSTEMV
    • MSNATIVE
    • VECTORCALL
  • pour le processeur ARM (32 bits)
    • AAPC
  • pour le processeur ARM (64 bits)
    • AAPCS64

ici est une grande page qui montre en fait les différences dans l'assemblage généré lors de la compilation pour différents ABIs.

une autre chose à mentionner est qu'un ABI n'est pas seulement pertinent à l'intérieur de le module exécutable de votre programme. C'est aussi utilisé par le linker pour s'assurer que votre programme appelle les fonctions de bibliothèque correctement. Vous avez plusieurs bibliothèques partagées fonctionnant sur votre ordinateur, et tant que votre compilateur sait ce QU'ils utilisent chacun, il peut appeler des fonctions à partir d'eux correctement sans faire exploser la pile.

votre compilateur comprendre comment appeler les fonctions de la Bibliothèque est extrêmement important. Sur une plate-forme hébergée (c'est-à-dire où un OS charge Programmes), votre programme ne peut même pas cligner des yeux sans faire un appel du noyau.

14
répondu Lakey 2016-12-30 20:40:46

fonctionnalité: un ensemble de contrats qui affectent le compilateur, les rédacteurs d'assemblage, le linker, et le système d'exploitation. Les contrats précisent comment les fonctions sont définies, où les paramètres sont passés, comment les paramètres sont passés, comment la fonction retourne le travail. Ceux-ci sont généralement spécifiques à un tuple (architecture de processeur, système d'exploitation).

entités Existantes: paramètre de mise en page, la fonction de la sémantique, de l'allocation de registres. Par exemple, les architectures ARM ont de nombreux Abi (APCS, EABI, GNU-EABI, peu importe un tas de cas historiques) - en utilisant l'ABI mixte, votre code ne fonctionnera tout simplement pas lorsque vous appelez au-delà des limites.

Consommateur: Le compilateur, de l'assemblée des écrivains, système d'exploitation, PROCESSEUR d'architecture spécifiques.

qui a besoin de ces détails? Le compilateur, les rédacteurs d'assemblage, les linkers qui font la génération de code (ou les exigences d'alignement), le système d'exploitation (la manipulation d'interruption, l'interface syscall). Si vous avez fait de la programmation d'assemblage, vous étiez conforme à un ABI!

C++ name mangling est un cas spécial - un éditeur de liens et l'éditeur de liens dynamique centrée question - si le nom d'amputation n'est pas normalisé, puis la liaison dynamique ne fonctionne pas. Désormais, le C++ ABI est appelé simplement cela, le C++ ABI. Il ne s'agit pas d'un problème au niveau de l'éditeur de liens, mais plutôt d'un problème de génération de code. Une fois que vous avez un binaire C++, il n'est pas possible de le rendre compatible avec un autre C++ ABI (nom mangling, exception manipulation) sans recompiler à partir de la source.

ELF est un format de fichier pour l'utilisation d'un chargeur et d'un chargeur dynamique. ELF est un format de conteneur pour le code binaire et les données, et en tant que tel spécifie L'ABI d'un morceau de code. Je ne considérerais pas ELF comme un ABI au sens strict, car les exécutables PE ne sont pas un ABI.

tous les Abi sont des instructions spécifiques. Un bras ABI n'aura pas de sens sur un processeur MSP430 ou x86_64.

Windows a plusieurs Abi - par exemple, fastcall et stdcall sont deux Abi d'usage courant. Le syscall ABI est de nouveau différent.

9
répondu Yann Ramin 2010-03-23 06:26:25

laissez-moi au moins répondre à une partie de votre question. Avec un exemple de la façon dont L'ABI Linux affecte les appels système, et pourquoi cela est utile.

un appel systemcall est un moyen pour un programme userspace de demander quelque chose au kernelspace. Il fonctionne en mettant le code numérique de l'appel et de l'argument dans un certain registre et le déclenchement d'une interruption. Qu'un switch se produit vers kernelspace et que le noyau regarde le code numérique et l'argument, traite la requête, remet le résultat dans un registre et déclenche un retour à l'espace utilisateur. Ceci est nécessaire par exemple lorsque l'application veut allouer de la mémoire ou d'ouvrir un fichier (syscalls "brk" et "ouvrir").

maintenant les syscalls ont des noms courts "brk", etc. et les codes op correspondants, ceux-ci sont définis dans un fichier d'en-tête spécifique au système. Tant que ces codes op restent les mêmes, vous pouvez exécuter les mêmes programmes compilés avec différents noyaux mis à jour sans avoir à recompiler. Si vous avez une interface utilisée par les binarys précompilés, donc ABI.

6
répondu snies 2010-01-31 09:56:07

la meilleure façon de faire la différence entre L'ABI et L'API est de savoir pourquoi et dans quel cas elle est utilisée:

pour x86-64 Il y a généralement un ABI (et pour x86 32-bit il y a un autre ensemble):

http://www.x86-64.org/documentation/abi.pdf

https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html

http://people.freebsd.org / ~obrien / amd64-elf-abi.pdf

Linux + FreeBSD + MacOSX le suivent avec quelques légères variations. Et Windows x64 a son propre ABI:

http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 /

connaissant L'ABI et en supposant que d'autres compilateurs le suivent aussi, alors les binaires savent théoriquement comment s'appeler les uns les autres (API bibliothèques en particulier) et passer des paramètres sur la pile ou par des registres, etc. Ou quels registres seront changés en appelant les fonctions etc. Essentiellement, ces connaissances aideront les logiciels à s'intégrer les uns aux autres. Connaissant l'ordre de la disposition des registres / stack, je peux facilement assembler différents logiciels écrits dans des assemblages ensemble sans trop de problèmes.

mais les API sont différentes:

Il s'agit d'un nom de fonctions de haut niveau, avec un argument défini, de sorte que si différents éléments logiciels sont construits à l'aide de ces API, ils peuvent être appelés les uns les autres. Mais une exigence supplémentaire du même ABI doit être respectée.

par exemple, Windows était compatible avec L'API POSIX:

https://en.wikipedia.org/wiki/Windows_Services_for_UNIX

https://en.wikipedia.org/wiki/POSIX

et Linux est aussi compatible POSIX. Mais les binaires ne peuvent pas être simplement déplacés et courir immédiatement. Mais parce qu'ils ont utilisé les mêmes noms dans L'API POSIX, vous pouvez prendre le même logiciel en C, le recompiler dans les différents OS, et le faire fonctionner immédiatement.

API sont destinés à faciliter l'intégration du logiciel - pré-étape de compilation. Si après la compilation, le logiciel peut sembler totalement différent - si L'ABI est différent.

ABI sont destinés à définir l'intégration exacte de logiciel le binaire / au niveau de l'assemblée.

4
répondu Peter Teoh 2016-01-22 05:02:37

pour appeler du code dans des bibliothèques partagées, ou du code d'appel entre des unités de compilation, le fichier objet doit contenir des étiquettes pour les appels. C++ manipule les noms des étiquettes de méthode afin d'imposer la dissimulation des données et de permettre les méthodes surchargées. C'est pourquoi vous ne pouvez pas mélanger des fichiers de compilateurs C++ différents à moins qu'ils ne prennent explicitement en charge le même ABI.

3
répondu Justin Smith 2010-02-01 03:48:23

résumé

il y a diverses interprétations et des opinions fortes de la couche exacte qui définissent un ABI (application interface binaire).

à mon avis, Un ABI est une Convention subjective de ce qui est considéré comme une plate-forme donnée pour une API spécifique. L'ABI est le "reste" des conventions qui "ne changeront pas" pour une API spécifique ou qui seront traitées par l'environnement runtime: executors, tools, linkers, les compilateurs, jvm, et OS.

définissant une Interface : ABI, API

Si vous souhaitez utiliser une bibliothèque comme joda-time, vous devez déclarer une dépendance sur joda-time-<major>.<minor>.<patch>.jar . La bibliothèque suit les meilleures pratiques et utilise version sémantique . Cela définit la compatibilité de L'API à trois niveaux:

  1. Patch - vous n'avez pas besoin de changer du tout votre code. La bibliothèque répare juste quelques bugs.
  2. Mineure - Vous n'avez pas besoin de modifier votre code depuis les ajouts
  3. Major-l'interface (API) est modifiée et vous pourriez avoir besoin de changer votre code.

pour que vous utilisiez une nouvelle version majeure de la même bibliothèque, beaucoup d'autres conventions doivent encore être respectées:

  • le langage binaire utilisé pour les bibliothèques définit le bytecode Java)
  • conventions d'Appel
  • conventions JVM
  • conventions de liaison
  • Exécution des conventions Tous ces éléments sont définis et gérés par les outils que nous utilisons.

Exemples

étude de cas Java

par exemple, Java a normalisé toutes ces conventions, non pas dans un outil, mais dans une spécification formelle JVM. La spécification a permis à d'autres fournisseurs de fournir un ensemble différent d'outils qui peuvent produire des bibliothèques compatibles.

Java fournit deux autres études de cas intéressantes pour ABI: les versions Scala et Dalvik machine virtuelle.

la machine virtuelle Dalvik a cassé l'ABI

la VM de Dalvik nécessite un type de bytecode différent du bytecode Java. Les bibliothèques Dalvik sont obtenues en convertissant le Java bytecode (avec la même API) pour Dalvik. De cette façon, vous pouvez obtenir deux versions de la même API: défini par l'original joda-time-1.7.2.jar . On pourrait m'appeler joda-time-1.7.2.jar et joda-time-1.7.2-dalvik.jar . Ils utilisent un autre ABI un est pour le standard Java VMs stack-oriented: Oracle un, IBM un, open Java ou tout autre; et le second ABI est celui autour de Dalvik.

Scala les versions successives sont incompatibles

Scala n'a pas de compatibilité binaire entre versions mineures de Scala: 2.X . Pour cette raison, la même API "io.réactivex " % % % "rxscala" % "0.26.5" dispose de trois versions (à l'avenir plus): pour Scala 2.10, 2.11 et 2.12. Qu'est-il changé? je ne sais pas pour l'instant , mais les binaires ne sont pas compatibles. Probablement les dernières versions ajoutent des choses qui rendent les bibliothèques inutilisables sur les vieilles machines virtuelles, probablement des choses liées aux conventions de liens/noms/paramètres.

Java les versions successives sont incompatible

Java a aussi des problèmes avec les versions majeures de la JVM: 4,5,6,7,8,9. Ils n'offrent qu'une rétrocompatibilité. JVM 9 sait utiliser le code compilé / ciblé (option -target de javac) pour toutes les autres versions, tandis que JVM 4 ne sait pas utiliser le code ciblé pour JVM 5. Tout ça pendant que vous avez une bibliothèque joda. Cette incompatibilité survole le radar grâce à différentes solutions:

  1. versioning sémantique: lorsque les bibliothèques ciblent des JVM supérieures, elles modifient généralement la version principale.
  2. utilisez JVM 4 comme L'ABI, et vous êtes en sécurité.
  3. Java 9 ajoute une spécification sur la façon dont vous pouvez inclure bytecode pour JVM ciblée spécifique dans la même bibliothèque.

Pourquoi ai-je commencé avec la définition de L'API?

API et ABI sont juste des conventions sur la façon dont vous définissez la compatibilité. Les couches inférieures sont génériques à l'égard d'un pléthore de haut niveau sémantique. C'est pourquoi il est facile de faire des conventions. Le premier type de conventions concerne l'alignement de la mémoire, l'encodage des bytes, les conventions d'appel, les grands et petits encodages, etc. En plus d'eux, vous obtenez les conventions exécutables comme d'autres décrites, conventions de liens, code d'octet intermédiaire comme celui utilisé par Java ou LLVM IR utilisé par GCC. Troisièmement, vous obtenez des conventions sur la façon de trouver des bibliothèques, comment les charger (voir Java les chargeurs de classe). Comme vous allez de plus en plus haut dans les concepts, vous avez de nouvelles conventions que vous considérez comme un donné. C'est pour ça qu'ils n'ont pas atteint le version sémantique . Ils sont implicites ou effondrés dans la version major . Nous pourrions modifier la version sémantique avec <major>-<minor>-<patch>-<platform/ABI> . C'est ce qui se passe réellement déjà: la plateforme est déjà un rpm , dll , jar (bytecode JVM), war (jvm+serveur web), apk , 2.11 (version Scala spécifique) et ainsi de suite. Lorsque vous dites APK, vous parlez déjà d'une partie ABI spécifique de votre API.

API peut être porté à différents ABI

Le haut niveau d'abstraction (les sources écrites contre le très-haut de l'API peuvent être recompilés/porté de tout autre bas niveau d'abstraction.

disons que j'ai des sources pour rxscala. Si les outils Scala sont changés je peux les recompiler pour que. Si la JVM change, je pourrais avoir des conversions automatiques de l'ancienne machine à la nouvelle sans me soucier des concepts de haut niveau. Bien que le portage peut être difficile aidera tout autre client. Si un nouveau système d'exploitation est créé en utilisant un code assembleur totalement différent, un traducteur peut être créé.

Api porté à travers les langues

il y a des API qui sont portées en plusieurs langues comme flux réactifs . En général, ils définissent des correspondances à des langues/plates-formes spécifiques. Je dirais que L'API est la spécification principale formellement définie en langage humain ou même un langage de programmation spécifique. Tous les autres" mappings " sont ABI dans un sens, sinon plus API que L'ABI habituel. Il en va de même pour les interfaces REST.

2
répondu raisercostin 2017-09-15 23:42:45

L'IPA doit être uniforme entre l'appelant et l'appelant pour être certain que l'appel est réussi. L'utilisation de la pile, registre, à la fin de la routine de la pile de la pop. Ce sont là les parties les plus importantes de L'ABI.

1
répondu Ignacio Vazquez-Abrams 2010-01-31 09:42:07

en bref et en philosophie, seules les choses d'un genre peuvent bien s'entendre, et L'ABI pourrait être considéré comme le genre dont les trucs logiciels fonctionnent ensemble.

1
répondu smwikipedia 2010-02-26 15:50:29

j'essayais aussi de comprendre la réponse D'ABI et JesperE était très utile.

D'un point de vue très simple, nous pouvons essayer de comprendre ABI en considérant la compatibilité binaire.

KDE wiki définit une bibliothèque comme compatible binaire " si un programme lié dynamiquement à une ancienne version de la bibliothèque continue à fonctionner avec de nouvelles versions de la bibliothèque sans avoir besoin de recompiler."Pour en savoir plus sur la liaison dynamique, reportez-vous à statique la liaison vs la liaison dynamique

maintenant, essayons d'examiner juste les aspects les plus basiques nécessaires pour qu'une bibliothèque soit compatible binaire (en supposant qu'il n'y ait aucun changement de code source à la bibliothèque):

  1. architecture de jeu d'instructions identiques ou compatibles en amont (instructions du processeur, structure du fichier de registre, organisation de la pile, types d'accès à la mémoire, ainsi que tailles, mise en page et alignement des types de données de base que le processeur peut accès direct)
  2. mêmes conventions d'appel
  3. même convention de manglage de nom (cela pourrait être nécessaire si par exemple un programme Fortran doit appeler une fonction de bibliothèque C++).

bien sûr, il ya beaucoup d'autres détails, mais c'est surtout ce que l'ABI couvre également.

plus spécifiquement pour répondre à votre question, de ce qui précède, nous pouvons en déduire:

ABI fonctionnalité: compatibilité binaire

entités existantes: programme existant/bibliothèques/OS

consommateur: bibliothèques, OS

Espérons que cette aide!

1
répondu blue_whale 2017-06-21 17:08:05

Application binary interface (ABI)

fonctionnalité:

  • la Traduction à partir de l'entreprise de programmation de modèle pour le sous-domaine du système de données type, Taille, alignement, la convention d'appel, qui contrôle comment les arguments des fonctions sont passés et les valeurs de retour récupérées; le numéros d'appel système et comment une application devrait faire des appels système au système d'exploitation; les compilateurs de langue de haut niveau" nom schéma de coupe, propagation d'exception et Convention d'appel entre compilateurs sur la même plate-forme, mais ne nécessitent pas de croix-compatibilité de plate-forme...

entités existantes:

  • blocs logiques qui participent directement à l'exécution du programme: ALU, registres à usage général, registres pour la cartographie mémoire/ I/O Des I/O, etc...

consommateurs:

  • Langue processeurs de l'éditeur de liens, assembleur...

ceux-ci sont nécessaires à quiconque doit s'assurer que les chaînes d'outils de construction fonctionnent comme un tout. Si vous écrivez un module en langage assembleur, un autre en Python, et qu'au lieu de votre propre boot-loader vous voulez utiliser un système d'exploitation, alors vos modules "application" fonctionnent au-delà des limites "binaires" et nécessitent l'accord d'une telle "interface".

C++ nom mangling parce que les fichiers d'objets de différents langages de haut niveau peuvent être nécessaires pour être liés dans votre application. Envisagez D'utiliser la bibliothèque standard de GCC pour faire des appels système vers Windows construit avec Visual C++.

ELF est une attente possible du linker à partir d'un fichier objet pour l'interprétation, Bien que JVM pourrait avoir une autre idée.

pour une application Windows RT Store, essayez de chercher ARM ABI si vous souhaitez vraiment faire un peu de construire outil-chaîne de travail ainsi.

1
répondu Chawathe Vipul 2017-09-15 23:34:19

le terme ABI est utilisé pour désigner deux concepts distincts mais liés.

quand on parle de compilateurs, on fait référence aux règles utilisées pour traduire des constructions de niveau source en constructions binaires. Quelle est la taille des types de données? comment fonctionne la pile de travail? Comment passer des paramètres à des fonctions? quels registres doivent être sauvegardés par l'appelant par rapport à l'appelant?

en parlant de bibliothèques, il se réfère à l'interface binaire présentée par une compilation bibliothèque. Cette interface est le résultat d'un certain nombre de facteurs, y compris le code source de la bibliothèque, les règles utilisées par le compilateur et, dans certains cas, les définitions ramassé d'autres bibliothèques.

les modifications à une bibliothèque peuvent briser L'ABI sans briser l'API. Considérons par exemple une bibliothèque avec une interface comme.

void initfoo(FOO * foo)
int usefoo(FOO * foo, int bar)
void cleanupfoo(FOO * foo)

et le programmeur d'application écrit le code comme

int dostuffwithfoo(int bar) {
  FOO foo;
  initfoo(&foo);
  int result = usefoo(&foo,bar)
  cleanupfoo(&foo);
  return result;
}

la demande programmeur ne se soucie pas de la taille ou la mise en page de FOO, mais le binaire d'application se termine avec une taille codée en dur de foo. Si le programmeur de la bibliothèque ajoute un champ supplémentaire à foo et que quelqu'un utilise le nouveau binaire de la bibliothèque avec l'ancien binaire d'application, alors la bibliothèque peut faire des accès mémoire hors limites.

OTOH si l'auteur de la bibliothèque avait conçu leur API comme.

FOO * newfoo(void)
int usefoo(FOO * foo, int bar)
void deletefoo((FOO * foo, int bar))

et le programmeur d'application écrit le code comme

int dostuffwithfoo(int bar) {
  FOO * foo;
  foo = newfoo();
  int result = usefoo(&foo,bar)
  deletefoo(&foo);
  return result;
}

alors le binaire d'application n'a pas besoin de savoir quoi que ce soit sur la structure de FOO, qui peuvent tous être cachés à l'intérieur de la bibliothèque. Le prix que vous payez pour cela est que les opérations segment sont impliqués.

1
répondu plugwash 2018-06-25 02:35:05