एपीआई और एबीआई के बीच अंतर


192

मैं लिनक्स सिस्टम प्रोग्रामिंग के लिए नया हूं और लिनक्स सिस्टम प्रोग्रामिंग पढ़ते हुए मैं एपीआई और एबीआई में आया हूं ।

एपीआई की परिभाषा:

एक एपीआई उन इंटरफेस को परिभाषित करता है जिसके द्वारा एक सॉफ्टवेयर का स्रोत स्तर पर दूसरे के साथ संचार होता है।

ABI की परिभाषा:

जबकि एक एपीआई एक स्रोत इंटरफ़ेस को परिभाषित करता है, एक एबीआई एक विशेष आर्किटेक्चर पर सॉफ्टवेयर के दो या अधिक टुकड़ों के बीच निम्न-स्तरीय बाइनरी इंटरफ़ेस को परिभाषित करता है। यह परिभाषित करता है कि कोई एप्लिकेशन अपने आप से कैसे इंटरएक्ट करता है, कैसे एक एप्लिकेशन कर्नेल के साथ इंटरैक्ट करता है, और कैसे एक एप्लिकेशन लाइब्रेरी के साथ इंटरैक्ट करता है।

एक स्रोत स्तर पर एक कार्यक्रम कैसे संवाद कर सकता है? स्रोत स्तर क्या है? यह वैसे भी स्रोत कोड से संबंधित है? या पुस्तकालय का स्रोत मुख्य कार्यक्रम में शामिल हो जाता है?

एकमात्र अंतर जो मुझे पता है कि एपीआई ज्यादातर प्रोग्रामर द्वारा उपयोग किया जाता है और एबीआई ज्यादातर कंपाइलर द्वारा उपयोग किया जाता है।


2
स्रोत स्तर से उनका मतलब कुछ इस तरह होता है जैसे फ़ंक्शन परिभाषाओं को उजागर करने के लिए फ़ाइल शामिल है
Anycorn

1
इसके अलावा stackoverflow.com/q/2171177/632951
Pacerier

जवाबों:


49

एपीआई वह है जो मनुष्य उपयोग करते हैं। हम सोर्स कोड लिखते हैं। जब हम कोई प्रोग्राम लिखते हैं और कुछ लाइब्रेरी फंक्शन का उपयोग करना चाहते हैं तो हम कोड लिखते हैं जैसे:

 long howManyDecibels = 123L;
 int ok = livenMyHills( howManyDecibels);

और हमें यह जानने की जरूरत है कि एक विधि है livenMyHills(), जो एक पूर्णांक पैरामीटर लेता है। एक प्रोग्रामिंग इंटरफ़ेस के रूप में यह सब स्रोत कोड में व्यक्त किया गया है। संकलक इसे निष्पादन योग्य निर्देशों में बदल देता है जो इस विशेष ऑपरेटिंग सिस्टम पर इस भाषा के कार्यान्वयन के अनुरूप हैं। और इस मामले में एक ऑडियो यूनिट पर कुछ निम्न स्तर के संचालन में परिणाम होता है। तो कुछ हार्डवेयर पर विशेष बिट्स और बाइट्स स्क्वर्ट किए जाते हैं। इसलिए रनटाइम पर बहुत सारे बाइनरी स्तर की कार्रवाई चल रही है, जो हम आमतौर पर नहीं देखते हैं।


309

एपीआई: एप्लिकेशन प्रोग्राम इंटरफ़ेस

यह सार्वजनिक प्रकार / चर / फ़ंक्शन का सेट है जिसे आप अपने एप्लिकेशन / लाइब्रेरी से उजागर करते हैं।

C / C ++ में यह वह है जो आप हेडर फाइलों में उजागर करते हैं जिन्हें आप एप्लिकेशन के साथ शिप करते हैं।

ABI: एप्लिकेशन बाइनरी इंटरफ़ेस

यह कैसे कंपाइलर एक एप्लिकेशन बनाता है।
यह चीजों को परिभाषित करता है (लेकिन यह सीमित नहीं है):

  • फ़ंक्शंस (रजिस्टर / स्टैक) के लिए पैरामीटर कैसे पारित किए जाते हैं।
  • जो स्टैक (कॉलर / कैली) से मापदंडों को साफ करता है।
  • जहां रिटर्न के लिए रिटर्न वैल्यू रखी गई है।
  • अपवाद कैसे प्रचारित करते हैं।

17
यह शायद सबसे अच्छा है संक्षिप्त क्या एक ABI, यह है कि मैंने कभी देखा है की व्याख्या; जी जे!
टेरीपी

3
आप लोगों को यह तय करने की आवश्यकता है कि यह उत्तर संक्षिप्त है या विस्तृत है। :)
जर्क

1
@ जर्क: चीजें संक्षिप्त और विस्तृत हो सकती हैं, वे परस्पर अनन्य नहीं हैं।
मार्टिन यॉर्क

@ लॉकीस्टारी, तो क्या एबीआई वास्तव में एपीआई भी नहीं है?
पचेरियर

4
@ स्पेसर: वे दोनों इंटरफेस हैं। लेकिन वे अमूर्तता के विभिन्न स्तरों पर हैं। API एप्लिकेशन डेवलपर स्तर पर है। एबीआई संकलक स्तर पर है (कहीं अनुप्रयोग डेवलपर कभी नहीं जाता है)।
मार्टिन यॉर्क

47

मैं ज्यादातर एपीआई-असंगत परिवर्तन, या एबीआई-असंगत परिवर्तन के अर्थ में इन शर्तों के पार आता हूं।

एक एपीआई परिवर्तन अनिवार्य रूप से जहां कोड है जो पिछले संस्करण के साथ संकलित होता है वह अब काम नहीं करेगा। ऐसा इसलिए हो सकता है क्योंकि आपने किसी फ़ंक्शन में एक तर्क जोड़ा, या अपने स्थानीय कोड के बाहर सुलभ किसी चीज़ का नाम बदल दिया। जब भी आप हेडर बदलते हैं, और यह आपको .c / .cpp फ़ाइल में कुछ बदलने के लिए मजबूर करता है, तो आपने एपीआई-परिवर्तन किया है।

एक ABI परिवर्तन वह कोड है जहां पहले से ही संस्करण 1 के खिलाफ संकलित किया गया है, अब कोडबेस (आमतौर पर एक पुस्तकालय) के संस्करण 2 के साथ काम नहीं करेगा। यह आम तौर पर एपीआई-असंगत परिवर्तन की तुलना में ट्रैक रखने के लिए मुश्किल है क्योंकि एक वर्ग में एक आभासी विधि को जोड़ने के रूप में सरल एबीआई असंगत हो सकता है।

मुझे लगता है कि ABI संगतता क्या है और इसे कैसे संरक्षित किया जाए, इसके लिए दो अत्यंत उपयोगी संसाधन मिले हैं:


4
उनकी पारस्परिक विशिष्टता को इंगित करने के लिए +1। उदाहरण के लिए, जावा के मुखर खोजशब्द का परिचय एक एपीआई-असंगत अभी तक ABI- संगत परिवर्तन docs.oracle.com/javase/7/docs/technotes/guides/language/… है
पचेरियर

आप अपने संसाधन अनुभाग के "3.6। असंगत पुस्तकालय" में जोड़ सकते tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html , जो सूचियों एक ABI परिवर्तन का कारण हो सकता है।
डेमी-ल्यून

20

यह मेरा आम स्पष्टीकरण है:

  • एपीआई - includeफ़ाइलों के बारे में सोचो । वे प्रोग्रामिंग इंटरफेस प्रदान करते हैं।
  • ABI - कर्नेल मॉड्यूल के बारे में सोचें। जब आप इसे कुछ कर्नेल पर चलाते हैं, तो इस पर सहमत होना पड़ता है कि फ़ाइलों के बिना संवाद कैसे किया जाए, जैसे कि निम्न-स्तरीय बाइनरी इंटरफ़ेस।

13

लिनक्स साझा लाइब्रेरी न्यूनतम रन करने योग्य एपीआई बनाम एबीआई उदाहरण

यह उत्तर मेरे अन्य उत्तर से निकाला गया है: एक एप्लीकेशन बाइनरी इंटरफ़ेस (ABI) क्या है? लेकिन मुझे लगा कि यह सीधे तौर पर इसका उत्तर देता है, और यह कि प्रश्न डुप्लिकेट नहीं हैं।

साझा पुस्तकालयों के संदर्भ में, "एक स्थिर एबीआई होने" का सबसे महत्वपूर्ण निहितार्थ यह है कि आपको पुस्तकालय परिवर्तन के बाद अपने कार्यक्रमों को फिर से स्थापित करने की आवश्यकता नहीं है।

जैसा कि हम नीचे दिए गए उदाहरण में देखेंगे, एबीआई, ब्रेकिंग प्रोग्राम को संशोधित करना संभव है, भले ही एपीआई अपरिवर्तित हो।

main.c

#include <assert.h>
#include <stdlib.h>

#include "mylib.h"

int main(void) {
    mylib_mystrict *myobject = mylib_init(1);
    assert(myobject->old_field == 1);
    free(myobject);
    return EXIT_SUCCESS;
}

mylib.c

#include <stdlib.h>

#include "mylib.h"

mylib_mystruct* mylib_init(int old_field) {
    mylib_mystruct *myobject;
    myobject = malloc(sizeof(mylib_mystruct));
    myobject->old_field = old_field;
    return myobject;
}

mylib.h

#ifndef MYLIB_H
#define MYLIB_H

typedef struct {
    int old_field;
} mylib_mystruct;

mylib_mystruct* mylib_init(int old_field);

#endif

संकलन और उसके साथ ठीक चलता है:

cc='gcc -pedantic-errors -std=c89 -Wall -Wextra'
$cc -fPIC -c -o mylib.o mylib.c
$cc -L . -shared -o libmylib.so mylib.o
$cc -L . -o main.out main.c -lmylib
LD_LIBRARY_PATH=. ./main.out

अब, मान लीजिए कि पुस्तकालय के वी 2 के लिए, हम करने के लिए एक नए क्षेत्र में जोड़ना चाहते हैं mylib_mystrictकहा जाता है new_field

यदि हमने फ़ील्ड को पहले की old_fieldतरह जोड़ा है:

typedef struct {
    int new_field;
    int old_field;
} mylib_mystruct;

और पुस्तकालय का पुनर्निर्माण किया, लेकिन नहीं main.out, तो मुखर विफल रहता है!

इसका कारण यह है लाइन:

myobject->old_field == 1

असेंबली जनरेट किया था intजो संरचना के पहले तक पहुंचने की कोशिश कर रहा है , जो अब new_fieldअपेक्षित के बजाय है old_field

इसलिए इस बदलाव ने एबीआई को तोड़ दिया।

यदि, हालांकि, हम इसके new_fieldबाद जोड़ते हैं old_field:

typedef struct {
    int old_field;
    int new_field;
} mylib_mystruct;

तब पुरानी जनरेट असेंबली अभी भी intसंरचना के पहले तक पहुंचती है, और कार्यक्रम अभी भी काम करता है, क्योंकि हमने एबीआई को स्थिर रखा है।

यहाँ GitHub पर इस उदाहरण का पूरी तरह से स्वचालित संस्करण है

इस ABI को स्थिर रखने का एक और तरीका यह होगा कि इसे mylib_mystructएक अपारदर्शी संरचना के रूप में माना जाता है , और केवल विधि सहायकों के माध्यम से अपने क्षेत्रों तक पहुंच बनाई जाती है। इससे एबीआई को स्थिर रखना आसान हो जाता है, लेकिन एक प्रदर्शन ओवरहेड को उकसाएगा क्योंकि हम अधिक फ़ंक्शन कॉल करेंगे।

एपीआई बनाम एबीआई

पिछले उदाहरण में, यह ध्यान रखना दिलचस्प है कि new_fieldपहले जोड़ने से old_field, केवल एबीआई को तोड़ दिया गया, लेकिन एपीआई को नहीं।

इसका मतलब यह है, अगर हमने main.cपुस्तकालय के खिलाफ अपने कार्यक्रम को फिर से तैयार किया है, तो यह परवाह किए बिना काम करेगा।

अगर हमने उदाहरण के लिए फ़ंक्शन सिग्नेचर को बदल दिया होता तो हम एपीआई भी तोड़ देते:

mylib_mystruct* mylib_init(int old_field, int new_field);

उस मामले में, main.cपूरी तरह से संकलन बंद हो जाएगा।

प्रोग्रामिंग एपीआई बनाम एबीआई

हम एपीआई परिवर्तनों को एक तीसरे प्रकार में वर्गीकृत कर सकते हैं: शब्दार्थ परिवर्तन।

उदाहरण के लिए, यदि हमने संशोधित किया था

myobject->old_field = old_field;

सेवा:

myobject->old_field = old_field + 1;

तब यह न तो एपीआई और न ही एबीआई main.cको तोड़ देता , लेकिन फिर भी टूट जाता!

ऐसा इसलिए है क्योंकि हमने प्रोग्राम के ध्यान देने योग्य पहलू के बजाय फ़ंक्शन के "मानव विवरण" को बदल दिया है।

मेरे पास बस दार्शनिक अंतर्दृष्टि थी जो एक अर्थ में सॉफ्टवेयर का औपचारिक सत्यापन "अर्थमेटिक एपीआई" से अधिक "प्रोग्रामेटिक रूप से सत्यापन योग्य एपीआई" में ले जाता है।

सिमेंटिक एपीआई बनाम प्रोग्रामिंग एपीआई

हम एपीआई परिवर्तनों को एक तीसरे प्रकार में वर्गीकृत कर सकते हैं: शब्दार्थ परिवर्तन।

सिमेंटिक एपीआई, आमतौर पर एक प्राकृतिक भाषा का वर्णन है कि एपीआई क्या करना चाहिए, आमतौर पर एपीआई प्रलेखन में शामिल होता है।

इसलिए कार्यक्रम का निर्माण किए बिना शब्दार्थ एपीआई को तोड़ना संभव है।

उदाहरण के लिए, यदि हमने संशोधित किया था

myobject->old_field = old_field;

सेवा:

myobject->old_field = old_field + 1;

तब यह न तो प्रोग्रामिंग एपीआई और न ही एबीआई main.cको तोड़ता था , लेकिन सिमेंटिक एपीआई टूट जाएगा।

प्रोग्राम को अनुबंध एपीआई की जाँच करने के दो तरीके हैं:

  • कोने के मामलों का एक गुच्छा परीक्षण करें। करने में आसान है, लेकिन आप हमेशा एक को याद कर सकते हैं।
  • औपचारिक सत्यापन । करने के लिए कठिन है, लेकिन एक "मानव" / मशीन सत्यापन योग्य तरीके से प्रलेखन और परीक्षणों को अनिवार्य रूप से एकजुट करने, शुद्धता के गणितीय प्रमाण का उत्पादन करता है! जब तक पाठ्यक्रम के अपने औपचारिक विवरण में एक बग नहीं है ;-)

उबंटू 18.10, जीसीसी 8.2.0 में परीक्षण किया गया।


2
तुम्हारा जवाब था जो मुझे एपीआई और एबीआई के बीच के अंतर को समझने में मदद करने के लिए पर्याप्त विस्तृत था। धन्यवाद!
राकेश रवि

9

( एक pplication बी inary I nterface) ऑपरेटिंग सिस्टम के साथ संयुक्त एक विशिष्ट हार्डवेयर प्लेटफॉर्म के लिए एक विनिर्देश। यह API ( A pplication P rogram I nterface) से परे एक कदम है , जो एप्लिकेशन से कॉलिंग को ऑपरेटिंग सिस्टम में परिभाषित करता है। ABI एक विशेष CPU परिवार के लिए एपीआई प्लस मशीन भाषा को परिभाषित करता है। एक एपीआई रनटाइम संगतता सुनिश्चित नहीं करता है, लेकिन एक एबीआई करता है, क्योंकि यह मशीन की भाषा, या रनटाइम, प्रारूप को परिभाषित करता है।

यहां छवि विवरण दर्ज करें

के सौजन्य से


9

मुझे एक विशिष्ट उदाहरण दें कि जावा में एबीआई और एपीआई कैसे भिन्न हैं।

एक ABI असंगत परिवर्तन होता है, अगर मैं Stringतर्क के रूप में तर्क लेने के लिए एक विधि A # m () बदलता हूं String...। यह एबीआई संगत नहीं है क्योंकि आपको उस कोड को फिर से इकट्ठा करना है जो कॉल कर रहा है, लेकिन यह एपीआई संगत है क्योंकि आप इसे कॉलर में किसी भी कोड परिवर्तन के बिना फिर से जमा करके हल कर सकते हैं।

यहाँ उदाहरण दिया गया है। कक्षा ए के साथ मेरा जावा पुस्तकालय है

// Version 1.0.0
public class A {
    public void m(String string) {
        System.out.println(string);
    }
}

और मेरे पास एक वर्ग है जो इस पुस्तकालय का उपयोग करता है

public class Main {
    public static void main(String[] args) {
        (new A()).m("string");
    }
}

अब, पुस्तकालय लेखक ने अपनी कक्षा A को संकलित किया, मैंने अपनी कक्षा Main का संकलन किया और यह सब अच्छी तरह से काम कर रहा है। A के नए संस्करण की कल्पना कीजिए

// Version 2.0.0
public class A {
    public void m(String... string) {
        System.out.println(string[0]);
    }
}

अगर मैं नई संकलित कक्षा A लेता हूं और पहले संकलित वर्ग Main के साथ एक साथ छोड़ता हूं, तो मुझे विधि को लागू करने के लिए अपवाद मिलेगा

Exception in thread "main" java.lang.NoSuchMethodError: A.m(Ljava/lang/String;)V
        at Main.main(Main.java:5)

अगर मैं मेन को रिजेक्ट करता हूं, तो यह तय है और सभी फिर से काम कर रहे हैं।


6

आपका प्रोग्राम (स्रोत कोड) उन मॉड्यूल के साथ संकलित किया जा सकता है जो उचित एपीआई प्रदान करते हैं ।

आपका प्रोग्राम (बाइनरी) उन प्लेटफार्मों पर चल सकता है जो उचित ABI प्रदान करते हैं ।

एपीआई प्रकार की परिभाषाओं, फ़ंक्शन परिभाषाओं, मैक्रोज़ को प्रतिबंधित करता है, कभी-कभी वैश्विक चर एक पुस्तकालय को उजागर करना चाहिए।

ABI आपको "प्लेटफ़ॉर्म" प्रदान करता है जो आपको प्रोग्राम को चलाने के लिए प्रदान करता है। मैं इसे 3 स्तरों पर विचार करना चाहता हूं:

  • प्रोसेसर स्तर - निर्देश सेट, कॉलिंग सम्मेलन

  • कर्नेल स्तर - सिस्टम कॉल कन्वेंशन, विशेष फ़ाइल पथ सम्मेलन (जैसे लिनक्स में /procऔर /sysफ़ाइलें), आदि।

  • ओएस स्तर - ऑब्जेक्ट प्रारूप, रनटाइम लाइब्रेरीज़ आदि।

क्रॉस-कंपाइलर नाम पर विचार करें arm-linux-gnueabi-gcc। "बांह" प्रोसेसर आर्किटेक्चर को इंगित करता है, "लिनक्स" कर्नेल को इंगित करता है, "ग्नू" इंगित करता है कि इसके लक्ष्य कार्यक्रम GNU के libc को रनटाइम लाइब्रेरी के रूप में arm-linux-androideabi-gccउपयोग करते हैं , जिससे एंड्रॉइड के libc कार्यान्वयन का उपयोग किया जाता है।


1
यह उनके बीच के अंतर और बहुत ही अनूठे परिप्रेक्ष्य में एक बहुत ही स्पष्ट व्याख्या है।
सजुकु

1

API- Application Programming Interfaceएक संकलन समय इंटरफ़ेस है जो डेवलपर द्वारा गैर-प्रोजेक्ट कार्यक्षमता जैसे कि लाइब्रेरी, ओएस, कोर कॉल को स्रोत कोड में उपयोग करने के लिए उपयोग किया जा सकता है

ABI[अबाउट] -Application Binary Interfaceएक रनटाइम इंटरफ़ेस है जो मशीन कोड में घटकों के बीच संचार के निष्पादन के दौरान एक प्रोग्राम द्वारा उपयोग किया जाता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.