एप्लिकेशन बाइनरी इंटरफ़ेस (ABI) क्या है?


492

मुझे कभी स्पष्ट रूप से समझ नहीं आया कि एक एबीआई क्या है। कृपया मुझे एक विकिपीडिया लेख की ओर इशारा न करें। अगर मैं इसे समझ पाता, तो मैं यहाँ इतनी लंबी पोस्ट नहीं डालता।

यह विभिन्न इंटरफेस के बारे में मेरी मानसिकता है:

एक टीवी रिमोट उपयोगकर्ता और टीवी के बीच एक इंटरफेस है। यह एक मौजूदा इकाई है, लेकिन अपने आप में बेकार (कोई कार्यक्षमता प्रदान नहीं करता है)। रिमोट पर उन प्रत्येक बटन के लिए सभी कार्यक्षमता टेलीविजन सेट में लागू की गई है।

इंटरफ़ेस: यह बीच 'मौजूदा इकाई "परत है functionalityऔर consumerहै कि कार्यक्षमता की। अपने आप से एक इंटरफ़ेस कुछ नहीं करता है। यह सिर्फ पीछे पड़ी कार्यक्षमता को आमंत्रित करता है।

अब यह निर्भर करता है कि उपयोगकर्ता कौन है विभिन्न प्रकार के इंटरफेस।

कमांड लाइन इंटरफेस (सीएलआई) कमांड मौजूदा संस्थाएं हैं, उपभोक्ता उपयोगकर्ता है और कार्यक्षमता पीछे है।

functionality: मेरी सॉफ़्टवेयर कार्यक्षमता जो कुछ उद्देश्य को हल करती है जिसके लिए हम इस इंटरफ़ेस का वर्णन कर रहे हैं।

existing entities: आदेशों

consumer: उपयोगकर्ता

ग्राफिकल यूजर इंटरफेस (जीयूआई) विंडो, बटन, आदि मौजूदा इकाइयां हैं, और फिर से उपभोक्ता उपयोगकर्ता है और कार्यक्षमता पीछे है।

functionality: मेरी सॉफ़्टवेयर कार्यक्षमता जो कुछ समस्या को हल करती है जिसके लिए हम इस इंटरफ़ेस का वर्णन कर रहे हैं।

existing entities: खिड़की, बटन आदि।

consumer: उपयोगकर्ता

एप्लिकेशन प्रोग्रामिंग इंटरफ़ेस (एपीआई) फ़ंक्शन (या अधिक सही होने के लिए) इंटरफेस (इंटरफेज आधारित प्रोग्रामिंग में) मौजूदा संस्थाएं हैं, उपभोक्ता यहां एक और प्रोग्राम नहीं उपयोगकर्ता है, और फिर से कार्यक्षमता इस परत के पीछे निहित है।

functionality: मेरी सॉफ़्टवेयर कार्यक्षमता जो कुछ समस्या को हल करती है जिसके लिए हम इस इंटरफ़ेस का वर्णन कर रहे हैं।

existing entities: फ़ंक्शंस, इंटरफ़ेसेस (कार्यों का सरणी)।

consumer: एक और कार्यक्रम / आवेदन।

एप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) यहां वह जगह है जहां मेरी समस्या शुरू होती है।

functionality: ???

existing entities: ???

consumer: ???

  • मैंने विभिन्न भाषाओं में सॉफ्टवेयर लिखा है और विभिन्न प्रकार के इंटरफेस (सीएलआई, जीयूआई, और एपीआई) प्रदान किए हैं, लेकिन मुझे यकीन नहीं है कि मैंने कभी कोई एबीआई प्रदान किया है।

विकिपीडिया कहता है:

ABI इस तरह के विवरण को कवर करते हैं

  • डेटा प्रकार, आकार और संरेखण;
  • कॉलिंग कन्वेंशन, जो नियंत्रित करता है कि फ़ंक्शन के तर्कों को कैसे पारित किया जाता है और पुनर्प्राप्त किए गए मान वापस आते हैं;
  • सिस्टम कॉल नंबर और एक एप्लीकेशन को ऑपरेटिंग सिस्टम पर सिस्टम कॉल कैसे करना चाहिए;

अन्य ABI इस तरह के विवरण का मानकीकरण करते हैं

  • C ++ नाम की मनुहार,
  • अपवाद प्रचार, और
  • एक ही मंच पर संकलक के बीच सम्मेलन बुलाना, लेकिन क्रॉस-प्लेटफॉर्म संगतता की आवश्यकता नहीं है।
  • कौन इन विवरणों की जरूरत है? कृपया ओएस मत कहो। मुझे विधानसभा प्रोग्रामिंग पता है। मुझे पता है कि लिंकिंग और लोडिंग कैसे काम करता है। मुझे पता है कि वास्तव में अंदर क्या होता है।

  • C ++ नाम मैन्युलेशन में क्यों आया? मुझे लगा कि हम बाइनरी स्तर पर बात कर रहे हैं। भाषाएं क्यों आती हैं?

वैसे भी, मैंने यह देखने के लिए [पीडीएफ] सिस्टम वी एप्लिकेशन बाइनरी इंटरफ़ेस संस्करण 4.1 (1997-03-18) डाउनलोड किया है कि इसमें क्या शामिल है। खैर, यह सबसे कोई मतलब नहीं था।

  • ELF फ़ाइल प्रारूप का वर्णन करने के लिए इसमें दो अध्याय (4th और 5th) क्यों हैं? वास्तव में, ये उस विनिर्देश के केवल दो महत्वपूर्ण अध्याय हैं। बाकी अध्याय "प्रोसेसर विशिष्ट" हैं। वैसे भी, मैं हालांकि यह एक पूरी तरह से अलग विषय है। कृपया नहीं कहता कि ELF फ़ाइल स्वरूप विनिर्देशों हैं ABI। यह परिभाषा के अनुसार एक इंटरफ़ेस होने के लिए योग्य नहीं है ।

  • मुझे पता है, चूंकि हम इतने निचले स्तर पर बात कर रहे हैं, यह बहुत विशिष्ट होना चाहिए। लेकिन मुझे यकीन नहीं है कि यह "निर्देश सेट आर्किटेक्चर (आईएसए)" कैसे विशिष्ट है?

  • मुझे Microsoft Windows 'ABI कहां मिल सकता है?

इसलिए, ये प्रमुख प्रश्न हैं जो मुझे परेशान कर रहे हैं।


7
"कृपया मत कहो, ओएस" कम्पाइलर्स को एबीआई जानने की जरूरत है। लिंक करने वालों को एबीआई जानने की जरूरत है। कर्नेल को ठीक से चलाने के लिए ABI को प्रोग्राम को सेट करने के लिए ABI को जानना आवश्यक है। जैसा कि C ++ के लिए नीचे देखें, यह जानबूझकर अतिभारित और निजी तरीकों के कारण लेबल को अस्पष्टता में बदल देता है, और लिंकर और किसी भी अन्य संकलक के पास इसके साथ काम करने के लिए संगत नाम प्रबंध करने की आवश्यकता होती है, दूसरे शब्दों में समान ABI।
जस्टिन स्मिथ

8
मुझे लगता है कि प्रश्न इतना स्पष्ट है; वास्तव में यह वर्णन करना कि उत्तर प्रारूप क्या है और अभी तक एक भी संतोषजनक उत्तर नहीं है जिसे स्वीकार किया जा सके।
किंवदंतियों 2

3
@ legends2k इस मुद्दे पर मेरी राय है कि ओपी वास्तव में जानता है कि एबीआई क्या है, लेकिन इसका एहसास नहीं होता है। प्रोग्रामर का विशाल बहुमत कभी भी एबीआई को डिजाइन या प्रदान नहीं करेगा, क्योंकि यह ओएस / प्लेटफॉर्म डिजाइनरों का काम है।
जेसपे

4
@ जेस्पर: मैं आपकी बात से सहमत हूँ। लेकिन शायद ओपी इसे स्पष्ट रूप से जानना चाहता है, प्रारूप एस / में वह फिट दिखता है, भले ही एस / उसे एक एबीआई प्रदान करने की आवश्यकता न हो।
लीजेंड्स 2

2
मैं अंजान था। हाल ही में इन सभी चीजों के साथ काम करते हुए। मुझे महसूस हुआ कि वास्तव में एबीआई क्या है। हाँ, मैं सहमत हूँ कि मेरा टेम्पलेट दोषपूर्ण है। एबीआई को मेरे खाके में फिट करना उचित नहीं है। धन्यवाद @ जैस्पर अपने जवाब को महसूस करने के लिए बस काम का अनुभव लिया।
पंजे

जवाबों:


533

"एबीआई" को समझने का एक आसान तरीका "एपीआई" से तुलना करना है।

आप पहले से ही एक एपीआई की अवधारणा से परिचित हैं। यदि आप, कुछ लाइब्रेरी या अपने OS की सुविधाओं का उपयोग करना चाहते हैं, तो आप एक एपीआई के खिलाफ प्रोग्राम करेंगे। एपीआई में डेटा प्रकार / संरचनाएं, स्थिरांक, कार्य आदि शामिल होते हैं, जिनका उपयोग आप अपने कोड में उस बाहरी घटक की कार्यक्षमता तक पहुंचने के लिए कर सकते हैं।

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

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

कभी-कभी, एबीआई परिवर्तन अपरिहार्य होते हैं। जब ऐसा होता है, तो उस लाइब्रेरी का उपयोग करने वाले कोई भी प्रोग्राम तब तक काम नहीं करेंगे जब तक कि वे लाइब्रेरी के नए संस्करण का उपयोग करने के लिए फिर से संकलित न हों। यदि एबीआई बदलता है लेकिन एपीआई नहीं करता है, तो पुराने और नए पुस्तकालय संस्करणों को कभी-कभी "स्रोत संगत" कहा जाता है। इसका तात्पर्य यह है कि जबकि एक पुस्तकालय संस्करण के लिए संकलित एक कार्यक्रम दूसरे के साथ काम नहीं करेगा, एक के लिए लिखा स्रोत कोड दूसरे के लिए फिर से संकलित होने पर काम करेगा।

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

एक ABI जरूरी नहीं है कि आप स्पष्ट रूप से कुछ प्रदान करें जब तक कि आप बहुत ही निम्न-स्तरीय सिस्टम डिज़ाइन कार्य नहीं कर रहे हों। यह भाषा-विशिष्ट नहीं है, क्योंकि (उदाहरण के लिए) C अनुप्रयोग और पास्कल अनुप्रयोग समान ABI का उपयोग उनके संकलित होने के बाद कर सकते हैं।

संपादित करें:SysV ABI डॉक्स में ELF फ़ाइल प्रारूप के बारे में अध्यायों के बारे में आपके प्रश्न के बारे में: इस जानकारी को शामिल करने का कारण है क्योंकि ELF प्रारूप ऑपरेटिंग सिस्टम और अनुप्रयोग के बीच इंटरफ़ेस को परिभाषित करता है। जब आप ओएस को प्रोग्राम चलाने के लिए कहते हैं, तो यह प्रोग्राम को एक निश्चित तरीके से फॉर्मेट होने की उम्मीद करता है और (उदाहरण के लिए) बाइनरी के पहले सेक्शन की उम्मीद करता है कि ईएलएफ हेडर हो सकता है जिसमें विशिष्ट मेमोरी ऑफसेट में कुछ जानकारी हो। यह इस प्रकार है कि एप्लिकेशन ऑपरेटिंग सिस्टम में अपने बारे में महत्वपूर्ण जानकारी का संचार करता है। यदि आप एक गैर-ईएलएफ बाइनरी प्रारूप (जैसे a.out या PE) में एक प्रोग्राम बनाते हैं, तो एक OS जो ELF- स्वरूपित अनुप्रयोगों की अपेक्षा करता है, बाइनरी फ़ाइल की व्याख्या नहीं कर पाएगा या एप्लिकेशन नहीं चला सकेगा।

IIRC, Windows वर्तमान में पोर्टेबल निष्पादन योग्य (या, PE) प्रारूप का उपयोग करता है । पीई प्रारूप के बारे में अधिक जानकारी के साथ उस विकिपीडिया पृष्ठ के "बाहरी लिंक" अनुभाग में लिंक हैं।

साथ ही, C ++ नाम के मेनटेनिंग के बारे में अपने नोट के बारे में: लाइब्रेरी फ़ाइल में किसी फ़ंक्शन का पता लगाने पर, फ़ंक्शन को आमतौर पर नाम से देखा जाता है। C ++ आपको फ़ंक्शन नामों को अधिभारित करने की अनुमति देता है, इसलिए किसी फ़ंक्शन को पहचानने के लिए अकेले नाम पर्याप्त नहीं है। C ++ संकलक के पास आंतरिक रूप से इस नाम से निपटने के अपने तरीके हैं, जिन्हें नामकरण कहा जाता है । एक ABI किसी फ़ंक्शन के नाम को एन्कोडिंग करने के मानक तरीके को परिभाषित कर सकता है ताकि किसी भिन्न भाषा या संकलक के साथ बनाए गए प्रोग्राम यह पता लगा सकें कि उन्हें क्या चाहिए। जब आप extern "c"C ++ प्रोग्राम में उपयोग करते हैं, तो आप संकलक को निर्देश दे रहे हैं कि वे उन रिकॉर्डिंग नामों के मानकीकृत तरीके का उपयोग करें जो अन्य सॉफ़्टवेयर द्वारा समझने योग्य हैं।


2
@bta, महान जवाब के लिए धन्यवाद। क्या सम्मेलन को बुलाना एक तरह का ABI है? धन्यवाद
कैमिनो

37
अच्छा उत्तर। सिवाय इसके कि एबीआई क्या है। एक ABI नियमों का एक समूह है जो कॉलिंग कन्वेंशन, और संरचनाओं को बिछाने के लिए नियमों को निर्धारित करता है। पास्कल सी अनुप्रयोगों से रिवर्स ऑर्डर में स्टैक पर तर्क पारित करता है, इसलिए पास्कल और सी कंपाइलर एक ही एबीआई के लिए संकलन नहीं करते हैं। सी और पास्कल संकलक के लिए संबंधित मानक यह सुनिश्चित करते हैं कि यह मामला होगा। C ++ कंपाइलर नामों को नियंत्रित करने के लिए "मानक" तरीके को परिभाषित नहीं कर सकता है, क्योंकि कोई मानक तरीका नहीं है। जब C ++ कंपाइलर विंडोज पर प्रतिस्पर्धा कर रहे थे, तब C ++ नाम के कन्वेंशन, C ++ कंपाइलर के बीच संगत नहीं थे।
रोबिन डेविस

1
निश्चित रूप से autotools.io/libtool/version.html और fedoramagazine.org/…
Pacerier

1
@RobinDavies: उन प्लेटफॉर्मों पर जहां पास्कल कंपाइलर्स ने अपने कॉलर्स द्वारा दिए गए फंक्शन पॉप तर्क कहे होंगे, सी कंपाइलर्स आमतौर पर उन माध्यमों को परिभाषित करते हैं जिनके द्वारा एक प्रोग्रामर यह संकेत दे सकता है कि विशेष फ़ंक्शन का उपयोग करना चाहिए, या उपयोग करने की उम्मीद की जानी चाहिए, उसी कॉलिंग कन्वेंशन के रूप में पास्कल कंपाइलर भले ही सी कंपाइलर्स आमतौर पर एक कन्वेंशन का उपयोग करते हैं, जहां फंक्शंस कहा जाता है कि स्टैक पर कुछ भी उनके कॉलर्स द्वारा रखा जाता है।
सुपरकैट

क्या मैं कह सकता हूं कि सी कंपाइलर द्वारा उत्पन्न फाइलें एबीआई हैं?
मट्टू राज

144

यदि आप असेंबली जानते हैं और ओएस-स्तर पर चीजें कैसे काम करती हैं, तो आप एक निश्चित एबीआई के अनुरूप हैं। ABI ऐसी चीज़ों को नियंत्रित करता है जैसे कैसे पैरामीटर पारित किए जाते हैं, जहाँ रिटर्न मान रखा जाता है। कई प्लेटफार्मों के लिए चुनने के लिए केवल एक एबीआई है, और उन मामलों में एबीआई सिर्फ "कैसे काम करता है"।

हालांकि, एबीआई चीजों को भी नियंत्रित करता है जैसे कि C ++ में कक्षाएं / ऑब्जेक्ट कैसे रखे जाते हैं। यह आवश्यक है यदि आप मॉड्यूल सीमाओं के पार वस्तु संदर्भों को पारित करने में सक्षम होना चाहते हैं या यदि आप अलग-अलग संकलक के साथ संकलित कोड को मिश्रण करना चाहते हैं।

इसके अलावा, यदि आपके पास 64-बिट OS है जो 32-बिट बायनेरिज़ को निष्पादित कर सकता है, तो आपके पास 32- और 64-बिट कोड के लिए अलग-अलग ABI होंगे।

सामान्य तौर पर, आप जिस भी कोड को एक ही निष्पादन योग्य में लिंक करते हैं, उसे उसी ABI के अनुरूप होना चाहिए। यदि आप विभिन्न ABI का उपयोग करके कोड के बीच संवाद करना चाहते हैं, तो आपको RPC या क्रमांकन प्रोटोकॉल के कुछ रूप का उपयोग करना चाहिए।

मुझे लगता है कि आप विभिन्न प्रकार के इंटरफेस में विशेषताओं के एक निश्चित सेट में निचोड़ने की बहुत कोशिश कर रहे हैं। उदाहरण के लिए, एक इंटरफेस जरूरी नहीं कि उपभोक्ताओं और उत्पादकों में विभाजित हो। एक इंटरफेस सिर्फ एक कन्वेंशन है जिसके द्वारा दो इकाइयाँ आपस में बातचीत करती हैं।

ABIs (आंशिक रूप से) ISA-agnostic हो सकते हैं। कुछ पहलू (जैसे कॉलिंग कन्वेंशन) ISA पर निर्भर करते हैं, जबकि अन्य पहलू (जैसे C ++ क्लास लेआउट) नहीं होते हैं।

संकलक लिखने वाले लोगों के लिए एक अच्छी तरह से परिभाषित एबीआई बहुत महत्वपूर्ण है। एक अच्छी तरह से परिभाषित एबीआई के बिना, इंटरऑपरेबल कोड उत्पन्न करना असंभव होगा।

संपादित करें: कुछ नोट्स स्पष्ट करने के लिए:

  • एबीआई में "बाइनरी" स्ट्रिंग्स या टेक्स्ट के उपयोग को बाहर नहीं करता है। यदि आप एक सीएलएल निर्यात करने वाले डीएलएल को जोड़ना चाहते हैं, तो कहीं न कहीं इसके तरीके और प्रकार के हस्ताक्षर एनकोडेड होने चाहिए। यहीं से C ++ नाम-मैनलिंग आता है।
  • यही कारण है कि आपने कभी भी एबीआई प्रदान नहीं किया है, जो कि अधिकांश प्रोग्रामर कभी नहीं करेंगे। ABI को प्लेटफ़ॉर्म (अर्थात ऑपरेटिंग सिस्टम) को डिज़ाइन करने वाले लोगों द्वारा प्रदान किया जाता है, और बहुत कम प्रोग्रामर को कभी-कभी व्यापक रूप से उपयोग किए जाने वाले ABI को डिज़ाइन करने का विशेषाधिकार प्राप्त होगा।

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

2
@jesperE, "ABI इस तरह की चीजों को नियंत्रित करता है कि कैसे पैरामीटर पारित किए जाते हैं, जहां रिटर्न मान रखा जाता है।" "cdecl, stdcall, fastcall, पास्कल" सही है?
कैमिनो

3
हाँ। उचित नाम "बुला सम्मेलन" है, जो एबीआई का एक हिस्सा है। en.wikipedia.org/wiki/X86_calling_conventions
JessperE

4
यह वह जगह है सही और सटीक शब्दाडंबर बिना जवाब (बल्कि शोर )!
नवाज

मैं थोड़ा असेंबली लिखने की सलाह देता हूं। इससे लोगों को एबीआई को और अधिक ठोस तरीके से समझने में मदद मिलेगी।
कुन्यु त्साई

40

आप वास्तव में सभी में एक ABI की जरूरत नहीं है -

  • आपके कार्यक्रम में कार्य नहीं हैं, और--
  • आपका कार्यक्रम एक एकल निष्पादन योग्य है जो अकेले चल रहा है (यानी एक एम्बेडेड सिस्टम) जहां यह शाब्दिक रूप से चलने वाली एकमात्र चीज़ है और इसे किसी और चीज़ से बात करने की आवश्यकता नहीं है।

एक निरीक्षण सारांश:

एपीआई: "यहां वे सभी कार्य हैं जिन्हें आप कॉल कर सकते हैं।"

ABI: "यह एक फ़ंक्शन को कॉल करने का तरीका है।"

ABI उन नियमों का समूह है जो संकलक और लिंकर आपके प्रोग्राम को संकलित करने के लिए पालन करते हैं ताकि यह ठीक से काम करे। ABI कई विषयों को कवर करते हैं:

  • संभवतः ABI का सबसे बड़ा और महत्वपूर्ण हिस्सा प्रक्रिया कॉल मानक है जिसे कभी-कभी "कॉलिंग कन्वेंशन" के रूप में जाना जाता है। कॉलिंग कन्वेंशन यह मानकीकृत करते हैं कि "फ़ंक्शन" को असेंबली कोड में कैसे अनुवादित किया जाता है।
  • ABIs यह भी निर्धारित करते हैं कि पुस्तकालयों में उजागर कार्यों के नाम का प्रतिनिधित्व कैसे किया जाना चाहिए ताकि अन्य कोड उन पुस्तकालयों को कॉल कर सकें और जान सकें कि क्या तर्क पारित किए जाने चाहिए। इसे "नाम मैनलिंग" कहा जाता है।
  • ABIs यह भी निर्धारित करते हैं कि किस प्रकार के डेटा प्रकारों का उपयोग किया जा सकता है, उन्हें कैसे संरेखित किया जाना चाहिए, और अन्य निम्न-स्तरीय विवरण।

कॉलिंग कन्वेंशन को गहराई से देखना, जिसे मैं एक ABI का मूल मानता हूं:

मशीन में "फ़ंक्शन" की कोई अवधारणा नहीं है। जब आप c जैसी उच्च-स्तरीय भाषा में कोई फ़ंक्शन लिखते हैं, तो कंपाइलर असेंबली कोड की एक लाइन उत्पन्न करता है _MyFunction1:। यह एक लेबल है , जो अंत में कोडांतरक द्वारा एक पते में हल हो जाएगा। यह लेबल असेंबली कोड में आपके "फ़ंक्शन" की "शुरुआत" को चिह्नित करता है। उच्च-स्तरीय कोड में, जब आप उस फ़ंक्शन को "कॉल" करते हैं, तो आप जो वास्तव में कर रहे हैं वह सीपीयू को उस लेबल के पते पर कूदने और वहां निष्पादित करने का कारण बन रहा है।

कूदने की तैयारी में, संकलक को महत्वपूर्ण सामान का एक गुच्छा करना चाहिए। कॉलिंग कन्वेंशन एक चेकलिस्ट की तरह है जो कंपाइलर यह सब करने के लिए इस प्रकार है:

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

कई अलग-अलग एबीआई / कॉलिंग कन्वेंशन हैं। कुछ मुख्य हैं:

  • X86 या x86-64 CPU (32-बिट वातावरण) के लिए:
    • CDECL
    • STDCALL
    • FASTCALL
    • VECTORCALL
    • THISCALL
  • X86-64 CPU (64-बिट वातावरण) के लिए:
    • SYSTEMV
    • MSNATIVE
    • VECTORCALL
  • एआरएम सीपीयू के लिए (32-बिट)
    • AAPCS
  • एआरएम सीपीयू के लिए (64-बिट)
    • AAPCS64

यहां एक महान पृष्ठ है जो वास्तव में विभिन्न एबीआई के लिए संकलन करते समय उत्पन्न विधानसभा के अंतर को दर्शाता है।

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

लाइब्रेरी फ़ंक्शंस को कॉल करने के लिए आपकी संकलक समझ अत्यंत महत्वपूर्ण है। एक होस्ट किए गए प्लेटफ़ॉर्म पर (वह है, जहां एक ओएस प्रोग्राम लोड करता है), आपका प्रोग्राम कर्नेल कॉल किए बिना भी ब्लिंक नहीं कर सकता है।


19

एक एप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) एक एपीआई के समान है, लेकिन फ़ंक्शन स्रोत कोड स्तर पर कॉलर तक पहुंच योग्य नहीं है। केवल एक बाइनरी प्रतिनिधित्व सुलभ / उपलब्ध है।

ABI को प्रोसेसर-आर्किटेक्चर स्तर या OS स्तर पर परिभाषित किया जा सकता है। संकलक के कोड-जनरेटर चरण के बाद एबीआई मानक हैं। मानक ओएस या प्रोसेसर द्वारा या तो तय किया जाता है।

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

मौजूदा निकाय: मशीन कोड फॉर्म में कार्य।

उपभोक्ता: एक अन्य फ़ंक्शन (किसी अन्य भाषा में एक सहित, एक अन्य संकलक द्वारा संकलित, या किसी अन्य लिंकर द्वारा लिंक)।


आर्किटेक्चर द्वारा ABI को क्यों परिभाषित किया जाएगा? एक ही आर्किटेक्चर पर अलग-अलग OS अलग-अलग ABI को परिभाषित क्यों नहीं कर पाएंगे?
एंड्रियास हैफेरबर्ग

10

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

मौजूदा इकाइयाँ: पैरामीटर लेआउट, फ़ंक्शन शब्दार्थ, रजिस्टर आवंटन। उदाहरण के लिए, ARM आर्किटेक्चर में कई ABI (APCS, EABI, GNU-EABI, कभी भी ऐतिहासिक मामलों का एक समूह नहीं होता) - मिश्रित ABI का उपयोग करने से आपका कोड बस सीमाओं के पार कॉल करते समय काम नहीं करेगा।

उपभोक्ता: संकलक, विधानसभा लेखक, ऑपरेटिंग सिस्टम, सीपीयू विशिष्ट वास्तुकला।

कौन इन विवरणों की जरूरत है? संकलक, असेंबली राइटर, लिंकर्स जो कोड जनरेशन (या एलाइनमेंट रिक्वायरमेंट्स), ऑपरेटिंग सिस्टम (इंटरप्ट हैंडलिंग, सिस्कॉल इंटरफेस) करते हैं। यदि आपने असेंबली प्रोग्रामिंग की थी, तो आप एक ABI के अनुरूप थे!

C ++ नाम मैनलिंग एक विशेष मामला है - इसका लिंकर और डायनेमिक लिंकर केंद्रित मुद्दा है - यदि नाम मैनिंजिंग को मानकीकृत नहीं किया जाता है, तो डायनेमिक लिंकिंग काम नहीं करेगा। इसके बाद, C ++ ABI को सिर्फ C ++ ABI कहा जाता है। यह एक लिंकर स्तर का मुद्दा नहीं है, बल्कि एक कोड पीढ़ी का मुद्दा है। एक बार आपके पास C ++ बाइनरी होने के बाद, स्रोत से पुन: उपयोग किए बिना इसे किसी अन्य C ++ ABI (नाम का प्रबंधन, अपवाद से निपटने) के साथ संगत करना संभव नहीं है।

ELF एक लोडर और डायनेमिक लिंकर के उपयोग के लिए एक फ़ाइल प्रारूप है। ELF बाइनरी कोड और डेटा के लिए एक कंटेनर प्रारूप है, और जैसा कि कोड के एक टुकड़े के ABI को निर्दिष्ट करता है। मैं सख्त अर्थ में ELF को ABI नहीं मानूंगा, क्योंकि PE निष्पादक एक ABI नहीं हैं।

सभी एबीआई अनुदेश सेट विशिष्ट हैं। एक एआरएम एबीआई एक एमएसपी 430 या x86_64 प्रोसेसर पर कोई मतलब नहीं रखेगा।

विंडोज में कई ABI हैं - उदाहरण के लिए, fastcall और stdcall दो आम उपयोग ABI हैं। Syscall ABI फिर से अलग है।


9

मुझे कम से कम अपने प्रश्न के एक भाग का उत्तर दें। लिनक्स ABI कैसे सिस्टमकॉल को प्रभावित करता है, और क्यों यह उपयोगी है, इस के एक उदाहरण के साथ।

एक systemcall एक उपयोगकर्ता कार्यक्रम के लिए कुछ के लिए kernelspace पूछने का एक तरीका है। यह एक निश्चित रजिस्टर में कॉल और तर्क के लिए संख्यात्मक कोड डालकर काम करता है और एक बाधा को ट्रिगर करता है। एक स्विच कर्नेलस्पेस के लिए होता है और कर्नेल संख्यात्मक कोड को देखता है और तर्क, अनुरोध को संभालता है, परिणाम को एक रजिस्टर में डालता है और स्विच को वापस यूजरस्पेस पर चलाता है। यह उदाहरण के लिए आवश्यक है जब एप्लिकेशन मेमोरी आवंटित करना चाहता है या एक फ़ाइल (syscalls "brk" और "open") खोलना चाहता है।

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


4

साझा पुस्तकालयों में कोड कॉल करने के लिए, या संकलन इकाइयों के बीच कॉल कोड के लिए, ऑब्जेक्ट फ़ाइल में कॉल के लिए लेबल शामिल करने की आवश्यकता है। C ++ डेटा को छुपाने और ओवरलोड तरीकों के लिए अनुमति देने के लिए मेथड लेबल्स के नाम का प्रबंधन करता है। यही कारण है कि जब तक वे स्पष्ट रूप से एक ही ABI का समर्थन नहीं करते हैं तब तक आप विभिन्न C ++ कंपाइलर से फ़ाइलों को नहीं मिला सकते हैं।


4

ABI और API के बीच अंतर करने का सबसे अच्छा तरीका यह जानना है कि इसका उपयोग क्यों और क्या किया जाता है:

X86-64 के लिए आम तौर पर एक ABI होता है (और x86 32-बिट के लिए एक और सेट होता है):

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

लिनक्स + फ्रीबीएसडी + मैकओएसएक्स कुछ मामूली बदलावों के साथ इसका पालन करते हैं। और Windows x64 का अपना ABI है:

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

एबीआई को जानने और अन्य संकलक के रूप में अच्छी तरह से इसका पालन करते हैं, तो बायनेरिज़ सैद्धांतिक रूप से जानते हैं कि एक दूसरे को कैसे कॉल करें (विशेष रूप से पुस्तकालयों एपीआई) और स्टैक के ऊपर या रजिस्टरों आदि से पैरामीटर पारित करें या फ़ंक्शन आदि कॉल करने पर क्या रजिस्टरों को बदल दिया जाएगा। अनिवार्य रूप से ये ज्ञान सॉफ्टवेयर को एक दूसरे के साथ एकीकृत करने में मदद करेंगे। रजिस्टरों / स्टैक लेआउट के आदेश को जानने के बाद मैं आसानी से विभिन्न समस्याओं के बिना असेंबली में लिखे गए अलग-अलग सॉफ़्टवेयर को एक साथ टुकड़ा कर सकता हूं।

लेकिन एपीआई अलग हैं:

यह एक उच्च स्तरीय फ़ंक्शन नाम है, जिसमें तर्क परिभाषित है, जैसे कि यदि इन एपीआई का उपयोग करके अलग-अलग सॉफ़्टवेयर टुकड़े का निर्माण होता है, तो MAY एक दूसरे में कॉल करने में सक्षम हो सकते हैं। लेकिन SAME ABI की अतिरिक्त आवश्यकता का पालन किया जाना चाहिए।

उदाहरण के लिए, Windows POSIX API के अनुरूप हुआ करता था:

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

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

और लिनक्स POSIX अनुरूप है। लेकिन बायनेरिज़ को केवल स्थानांतरित नहीं किया जा सकता है और तुरंत चलाया जा सकता है। लेकिन क्योंकि उन्होंने POSIX आज्ञाकारी एपीआई में समान NAMES का उपयोग किया था, आप C में समान सॉफ़्टवेयर ले सकते हैं, इसे अलग-अलग OS में फिर से जोड़ सकते हैं, और तुरंत इसे चला सकते हैं।

एपीआई सॉफ्टवेयर के एकीकरण को कम करने के लिए है - पूर्व संकलन चरण। संकलन के बाद सॉफ्टवेयर पूरी तरह से अलग दिख सकता है - अगर एबीआई अलग हैं।

ABI बाइनरी / असेंबली स्तर पर सॉफ्टवेयर के सटीक एकीकरण को परिभाषित करने के लिए है।


Windows x86-64 कॉलिंग कन्वेंशन SysV कॉलिंग कन्वेंशन का उपयोग नहीं करता है जो अन्य सभी x86-64 OSes उपयोग करते हैं। लिनक्स / ओएस एक्स / फ्रीबीएसडी सभी समान कॉलिंग सम्मेलन साझा करते हैं, लेकिन वे पूर्ण एबीआई साझा नहीं करते हैं । एक OS के ABI में सिस्टम-कॉल नंबर शामिल हैं। उदाहरण के लिए freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/… कहता है कि SYS_execve32 बिट लाइन पर 11 है, लेकिन फ्रीबीएसडी पर 59 है।
पीटर कॉर्डेस

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

आप अभी भी एक कॉलिंग कन्वेंशन और एक पूर्ण ABI (सिस्टम कॉल और सब कुछ) के बीच अंतर को याद कर रहे हैं। आप लिनक्स पर कुछ FreeBSD बायनेरिज़ चला सकते हैं, क्योंकि Linux (कर्नेल) एक FreeBSD संगतता परत प्रदान करता है। फिर भी, यह बायनेरिज़ तक सीमित है जो फ्रीबीएसडी एबीआई के किसी भी हिस्से का उपयोग करने की कोशिश नहीं करता है जो लिनक्स प्रदान नहीं करता है। (जैसे कोई भी FreeBSD- केवल सिस्टम कॉल)। ABI- संगत का अर्थ है कि आप दोनों प्रणालियों पर एक ही बाइनरी चला सकते हैं, न कि केवल वे समान रूप से संकलित करेंगे।
पीटर कॉर्ड्स

"FreeBSD संगतता परत", उस के बारे में कभी नहीं सुना। क्या आप प्रासंगिक लिनक्स कर्नेल स्रोत कोड को इंगित कर सकते हैं? लेकिन रिवर्स मौजूद है: freebsd.org/doc/en_US.ISO8859-1/books/handbook/linuxemu.html
पीटर तेह

यह ऐसा कुछ नहीं है जिसका मैं उपयोग करता हूं। मुझे लगा कि ऐसा कुछ मौजूद है, लेकिन शायद अब ऐसा नहीं है। tldp.org/HOWTO/Linux+FreeBSD-6.html का कहना है कि यह अप्रमाणित है, और यह कि 2000 से है। xD। unix.stackexchange.com/questions/172038/… पुष्टि करता है कि इसे छोड़ दिया गया था और फिर से कभी नहीं किया गया (क्योंकि कोई भी इसे बुरी तरह से पूरा नहीं करना चाहता था)। personality(2)सेट कर सकते हैं PER_BSD। मुझे लगता है कि मुझे हर समय आउटपुट personality(PER_LINUX)में देखना याद है strace, लेकिन आधुनिक 64 बिट लिनक्स बायनेरिज़ अब ऐसा नहीं करते हैं।
पीटर कॉर्डेस

4

लिनक्स साझा पुस्तकालय न्यूनतम चल एबीआई उदाहरण

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

उदाहरण के लिए:

  • यदि आप एक साझा पुस्तकालय बेच रहे हैं, तो आप अपने उपयोगकर्ताओं को हर उस चीज़ को पुनः प्राप्त करने की झुंझलाहट से बचाते हैं जो आपकी लाइब्रेरी पर निर्भर करती है

  • यदि आप बंद स्रोत प्रोग्राम बेच रहे हैं, जो उपयोगकर्ता के वितरण में मौजूद एक साझा पुस्तकालय पर निर्भर करता है, तो आप कम प्रीडेट्स जारी कर सकते हैं और परीक्षण कर सकते हैं यदि आप निश्चित हैं कि एबीआई लक्ष्य ओएस के कुछ संस्करणों में स्थिर है।

    यह सी मानक पुस्तकालय के मामले में विशेष रूप से महत्वपूर्ण है, जो आपके सिस्टम से कई कार्यक्रमों को लिंक करता है।

अब मैं इसका एक न्यूनतम ठोस रननीय उदाहरण प्रदान करना चाहता हूं।

main.c

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

#include "mylib.h"

int main(void) {
    mylib_mystruct *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_mystructकहा जाता है 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को तोड़ता था , लेकिन सिमेंटिक एपीआई टूट जाएगा।

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

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

    यह अवधारणा स्वयं गणित की औपचारिकता से निकटता से संबंधित है: /math/53969/what-does-formal-mean/3297537#3297537

C / C ++ साझा लाइब्रेरी ABI को तोड़ने वाली हर चीज़ की सूची

TODO: अंतिम सूची खोजें / बनाएं:

जावा न्यूनतम रननीय उदाहरण

जावा में बाइनरी संगतता क्या है?

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


3

ABI को कॉलर और कैली के बीच लगातार होना चाहिए ताकि कॉल सफल हो सके। स्टैक का उपयोग, रजिस्टर उपयोग, एंड-ऑफ-रूटीन स्टैक पॉप। ये सभी ABI के सबसे महत्वपूर्ण भाग हैं।


3

सारांश

सटीक परत की विभिन्न व्याख्या और मजबूत राय हैं जो एक एबीआई (एप्लिकेशन बाइनरी इंटरफ़ेस) को परिभाषित करती हैं।

मेरे विचार में एक ABI एक विशिष्ट API के लिए दिए गए / प्लेटफॉर्म पर विचार किया जाने वाला एक व्यक्तिपरक सम्मेलन है। ABI सम्मेलनों का "आराम" है जो एक विशिष्ट एपीआई के लिए "नहीं बदलेगा" या जिसे रनटाइम वातावरण द्वारा संबोधित किया जाएगा: निष्पादक, उपकरण, लिंकर, संकलक, जेवीएम, और ओएस।

एक इंटरफ़ेस को परिभाषित करना : एबीआई, एपीआई

यदि आप जोडा-टाइम जैसी लाइब्रेरी का उपयोग करना चाहते हैं, तो आपको एक निर्भरता की घोषणा करनी चाहिए joda-time-<major>.<minor>.<patch>.jar। पुस्तकालय सर्वोत्तम प्रथाओं का पालन करता है और सिमेंटिक संस्करण का उपयोग करता है । यह एपीआई संगतता को तीन स्तरों पर परिभाषित करता है:

  1. पैच - आपको अपने सभी कोड बदलने की आवश्यकता नहीं है। पुस्तकालय कुछ कीड़े ठीक करता है।
  2. लघु - परिवर्धन के बाद से आपको अपना कोड बदलने की आवश्यकता नहीं है
  3. प्रमुख - इंटरफ़ेस (एपीआई) बदल गया है और आपको अपना कोड बदलने की आवश्यकता हो सकती है।

आपके लिए उसी लाइब्रेरी की एक नई प्रमुख रिलीज़ का उपयोग करने के लिए कई अन्य सम्मेलनों का अभी भी सम्मान किया जाना बाकी है:

  • पुस्तकालयों के लिए उपयोग की जाने वाली द्विआधारी भाषा (जावा में JVM लक्ष्य संस्करण जो जावा बाइटकोड को परिभाषित करता है)
  • अधिवेशन बुला रहे हैं
  • जेवीएम सम्मेलन
  • सम्मेलनों को जोड़ना
  • रनटाइम कन्वेंशन इन सभी को परिभाषित और प्रबंधित टूल द्वारा उपयोग किया जाता है।

उदाहरण

जावा केस स्टडी

उदाहरण के लिए, जावा ने इन सभी सम्मेलनों को एक उपकरण में नहीं, बल्कि एक औपचारिक जेवीएम विनिर्देश में मानकीकृत किया। विनिर्देशन ने अन्य विक्रेताओं को उपकरणों का एक अलग सेट प्रदान करने की अनुमति दी जो संगत पुस्तकालयों का उत्पादन कर सकते हैं।

जावा ABI के लिए दो अन्य दिलचस्प केस स्टडीज प्रदान करता है: स्काला संस्करण और Dalvik वर्चुअल मशीन।

Dalvik वर्चुअल मशीन ने ABI को तोड़ दिया

Dalvik VM को Java bytecode की तुलना में एक अलग प्रकार के बायटेकोड की आवश्यकता है। Dalvik पुस्तकालयों Dalvik के लिए जावा बाइटकोड (एक ही एपीआई के साथ) परिवर्तित करके प्राप्त कर रहे हैं। इस तरह आप एक ही एपीआई के दो संस्करण प्राप्त कर सकते हैं: मूल द्वारा परिभाषित joda-time-1.7.2.jar। हम मुझे joda-time-1.7.2.jarऔर बुला सकते हैं joda-time-1.7.2-dalvik.jar। वे एक अलग ABI का उपयोग करते हैं जो स्टैक-ओरिएंटेड मानक Java vms के लिए है: Oracle का एक, IBM का एक, ओपन जावा या कोई अन्य; और दूसरा एबीआई दलविक के आसपास है।

स्काला क्रमिक रिलीज असंगत हैं

स्काला में मामूली स्काला संस्करणों के बीच द्विआधारी संगतता नहीं है: 2.X। इस कारण से समान API "io.reactivex" %% "rxscala"% "0.26.5" के तीन संस्करण हैं (भविष्य में अधिक): Scala 2.10, 2.11 और 2.12 के लिए। क्या बदला है? मैं अभी के लिए नहीं जानता , लेकिन बायनेरिज़ संगत नहीं हैं। संभवतः नवीनतम संस्करण उन चीज़ों को जोड़ता है जो पुराने आभासी मशीनों पर पुस्तकालयों को अनुपयोगी बनाते हैं, शायद लिंकिंग / नामकरण / पैरामीटर सम्मेलनों से संबंधित चीजें।

जावा क्रमिक रिलीज असंगत हैं

जावा को जेवीएम: 4,5,6,7,8,9 के प्रमुख रिलीज के साथ भी समस्याएं हैं। वे केवल पिछड़ी संगतता प्रदान करते हैं। Jvm9 -targetसभी अन्य संस्करणों के लिए कोड संकलित / लक्षित (javac का विकल्प) चलाना जानता है , जबकि JVM 4 को पता नहीं है कि JVM 5 के लिए लक्षित कोड को कैसे चलाना है। ये सभी आपके पास एक joda-Library के होते हैं। यह असंगतता रडार को अलग-अलग समाधानों के लिए धन्यवाद देती है:

  1. शब्दार्थ संस्करण: जब पुस्तकालय उच्च JVM को लक्षित करते हैं तो वे आम तौर पर प्रमुख संस्करण बदल देते हैं।
  2. एबीवी के रूप में जेवीएम 4 का उपयोग करें, और आप सुरक्षित हैं।
  3. जावा 9 एक विनिर्देश जोड़ता है कि आप एक ही पुस्तकालय में विशिष्ट लक्षित जेवीएम के लिए बायटेकोड को कैसे शामिल कर सकते हैं।

मैंने एपीआई परिभाषा के साथ शुरुआत क्यों की?

एपीआई और एबीआई केवल कन्वेंशन हैं कि आप संगतता को कैसे परिभाषित करते हैं। निचली परतें उच्च स्तर के शब्दार्थों के बहुतायत के संबंध में सामान्य हैं। इसलिए कुछ कन्वेंशन करना आसान है। स्मृति संरेखण, बाइट एन्कोडिंग, कॉलन कन्वेंशन, बड़े और छोटे एंडियन एन्कोडिंग, आदि के बारे में पहली तरह के सम्मेलनों के बारे में हैं। उनमें से शीर्ष पर आप निष्पादन योग्य सम्मेलनों का वर्णन करते हैं, जैसे कि अन्य वर्णित, सम्मेलनों को जोड़ना, मध्यवर्ती बाइट कोड जैसे कि जावा या इस्तेमाल किया हुआ। एलएलवीएम आईआर का उपयोग जीसीसी द्वारा किया जाता है। तीसरा, आपको पुस्तकालयों को खोजने के तरीके, उन्हें लोड करने के तरीके (जावा क्लास लोडर देखें) पर कन्वेंशन मिलते हैं। जैसा कि आप अवधारणाओं में उच्च और उच्चतर जाते हैं, आपके पास नए सम्मेलन होते हैं जिन्हें आप दिए गए के रूप में मानते हैं। इसलिए उन्होंने इसे सिमेंटिक वर्जनिंग के लिए नहीं बनाया । वे निहित या ध्वस्त हैंसंस्करण। हम के साथ शब्दार्थ संस्करण में संशोधन कर सकते हैं <major>-<minor>-<patch>-<platform/ABI>। यह क्या वास्तव में पहले से ही हो रहा है: मंच पहले से ही है एक rpm, dll, jar(JVM बाईटकोड), war(JVM + वेब सर्वर), apk, 2.11(विशिष्ट स्काला संस्करण) और इतने पर। जब आप एपीके कहते हैं तो आप पहले से ही अपने एपीआई के एक विशिष्ट एबीआई भाग के बारे में बात करते हैं।

एपीआई को विभिन्न एबीआई में पोर्ट किया जा सकता है

एक अमूर्त के शीर्ष स्तर (उच्चतम एपीआई के खिलाफ लिखे गए स्रोतों को किसी अन्य निचले स्तर के अमूर्त में recompiled / ported किया जा सकता है।

मान लीजिए कि मेरे पास rxscala के लिए कुछ स्रोत हैं। यदि स्केला उपकरण बदल दिए जाते हैं तो मैं उन्हें उस पर फिर से जोड़ सकता हूं यदि JVM बदलता है तो मैं उच्च स्तर की अवधारणाओं से परेशान हुए बिना पुरानी मशीन से नई के लिए स्वचालित रूपांतरण कर सकता हूं। पोर्ट करना मुश्किल हो सकता है, किसी भी अन्य ग्राहक की मदद करेगा। यदि एक बिल्कुल अलग कोडांतरक कोड का उपयोग करके एक नया ऑपरेटिंग सिस्टम बनाया जाता है तो एक अनुवादक बनाया जा सकता है।

API भाषाओं में पोर्ट किए गए

एपीआई ऐसे होते हैं जो प्रतिक्रियाशील धाराओं की तरह कई भाषाओं में होते हैं । सामान्य तौर पर वे मैपिंग को विशिष्ट भाषाओं / प्लेटफार्मों में परिभाषित करते हैं। मैं तर्क दूंगा कि API मानव जीवन या एक विशिष्ट प्रोग्रामिंग भाषा में औपचारिक रूप से परिभाषित मास्टर विनिर्देश है। अन्य सभी "मैपिंग" एक अर्थ में एबीआई हैं, सामान्य एबीआई की तुलना में अधिक एपीआई। ऐसा ही REST इंटरफेस के साथ भी हो रहा है।


1

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


1

मैं एबीआई और जेस्पर के जवाब को समझने में भी मदद कर रहा था।

बहुत ही सरल दृष्टिकोण से, हम बाइनरी संगतता पर विचार करके एबीआई को समझने की कोशिश कर सकते हैं।

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

अब, आइए, पुस्तकालय के लिए द्विआधारी संगतता होने के लिए आवश्यक सबसे बुनियादी पहलुओं को देखने का प्रयास करें (यह मानते हुए कि पुस्तकालय के लिए कोई स्रोत कोड परिवर्तन नहीं हैं):

  1. समान / पिछड़े संगत निर्देश सेट आर्किटेक्चर (प्रोसेसर निर्देश, रजिस्टर फ़ाइल संरचना, स्टैक संगठन, मेमोरी एक्सेस प्रकार, आकार, लेआउट और बुनियादी डेटा प्रकारों के संरेखण के साथ प्रोसेसर सीधे पहुंच सकता है)
  2. वही कॉलिंग कन्वेंशन
  3. एक ही नाम मैनिंग कन्वेंशन (यदि कोई फोरट्रान प्रोग्राम को कुछ C ++ लाइब्रेरी फ़ंक्शन को कॉल करने की आवश्यकता है, तो यह आवश्यक हो सकता है)।

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

ऊपर से आपके प्रश्न का उत्तर देने के लिए विशेष रूप से, हम कटौती कर सकते हैं:

ABI कार्यक्षमता: बाइनरी संगतता

मौजूदा इकाइयाँ: मौजूदा कार्यक्रम / पुस्तकालय / ओएस

उपभोक्ता: पुस्तकालय, ओएस

उम्मीद है की यह मदद करेगा!


1

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

कार्यक्षमता:

  • प्रोग्रामर के मॉडल से अंतर्निहित सिस्टम के डोमेन डेटा प्रकार, आकार, संरेखण, कॉलिंग कन्वेंशन का अनुवाद, जो यह नियंत्रित करता है कि फ़ंक्शन के तर्क कैसे पारित किए जाते हैं और वापस लौटाए गए मान; सिस्टम कॉल नंबर और एक एप्लीकेशन को ऑपरेटिंग सिस्टम पर सिस्टम कॉल कैसे करना चाहिए; उच्च-स्तरीय भाषा संकलक का नाम प्रबंधन योजना, अपवाद प्रचार, और एक ही मंच पर संकलक के बीच सम्मेलन बुलाना, लेकिन क्रॉस-प्लेटफॉर्म संगतता की आवश्यकता नहीं है ...

मौजूदा संस्थाएँ:

  • तार्किक ब्लॉक जो सीधे कार्यक्रम के निष्पादन में भाग लेते हैं: ALU, सामान्य उद्देश्य रजिस्टर, मेमोरी / I / O मैपिंग ऑफ़ I / O, आदि के लिए रजिस्टर ...

उपभोक्ता:

  • भाषा प्रोसेसर लिंकर, कोडांतरक ...

इन्हें इसकी जरूरत होती है, जिन्हें यह सुनिश्चित करना होता है कि टूल-चेन पूरी तरह से काम करें। यदि आप असेंबली भाषा में एक मॉड्यूल, पायथन में एक और लिखते हैं, और अपने स्वयं के बूट-लोडर के बजाय एक ऑपरेटिंग सिस्टम का उपयोग करना चाहते हैं, तो आपके "एप्लिकेशन" मॉड्यूल "बाइनरी" सीमाओं पर काम कर रहे हैं और इस तरह के "इंटरफ़ेस" के समझौते की आवश्यकता है।

C ++ नाम मैनलिंग क्योंकि विभिन्न उच्च-स्तरीय भाषाओं की ऑब्जेक्ट फ़ाइलों को आपके एप्लिकेशन में लिंक किया जाना आवश्यक है। दृश्य C ++ के साथ निर्मित विंडोज के लिए जीसीसी मानक लाइब्रेरी मेकिंग सिस्टम कॉल का उपयोग करने पर विचार करें।

ELF व्याख्या के लिए ऑब्जेक्ट फ़ाइल से लिंकर की एक संभावित अपेक्षा है, हालांकि JVM के पास कुछ अन्य विचार हो सकता है।

विंडोज आरटी स्टोर ऐप के लिए, एआरएम एबीआई को खोजने का प्रयास करें यदि आप वास्तव में कुछ बिल्ड टूल-चेन काम एक साथ करना चाहते हैं।


1

ABI शब्द का उपयोग दो अलग-अलग लेकिन संबंधित अवधारणाओं को संदर्भित करने के लिए किया जाता है।

जब संकलक के बारे में बात करते हैं तो यह स्रोत-स्तर के निर्माणों से द्विआधारी निर्माणों में अनुवाद करने के लिए उपयोग किए जाने वाले नियमों को संदर्भित करता है। डेटा प्रकार कितने बड़े हैं? स्टैक कैसे काम करता है? मैं कार्यों के लिए पैरामीटर कैसे पास करूं? कौन से रजिस्टर को कॉलर बनाम कैली द्वारा बचाया जाना चाहिए?

पुस्तकालयों के बारे में बात करते समय यह संकलित पुस्तकालय द्वारा प्रस्तुत द्विआधारी इंटरफ़ेस को संदर्भित करता है। यह इंटरफ़ेस पुस्तकालय के स्रोत कोड, कंपाइलर द्वारा उपयोग किए जाने वाले नियमों और कुछ मामलों में अन्य पुस्तकालयों से उठाए गए नियमों सहित कई कारकों का परिणाम है।

एक पुस्तकालय में परिवर्तन एपीआई को तोड़ने के बिना एबीआई को तोड़ सकता है। उदाहरण के लिए एक इंटरफ़ेस जैसे पुस्तकालय के साथ विचार करें।

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

और एप्लिकेशन प्रोग्रामर जैसे कोड लिखता है

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

एप्लिकेशन प्रोग्रामर FOO के आकार या लेआउट के बारे में परवाह नहीं करता है, लेकिन एप्लिकेशन बाइनरी फू के हार्डकोडेड आकार के साथ समाप्त होता है। यदि लाइब्रेरी प्रोग्रामर फू करने के लिए एक अतिरिक्त फ़ील्ड जोड़ता है और कोई व्यक्ति पुराने एप्लिकेशन बाइनरी के साथ नई लाइब्रेरी बाइनरी का उपयोग करता है तो लाइब्रेरी सीमा मेमोरी एक्सेस से बाहर कर सकती है।

OTOH यदि पुस्तकालय लेखक ने अपने API की तरह डिजाइन किया था।

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

और एप्लिकेशन प्रोग्रामर जैसे कोड लिखता है

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

तब एप्लिकेशन बाइनरी को FOO की संरचना के बारे में कुछ भी जानने की आवश्यकता नहीं है, यह सब पुस्तकालय के अंदर छिपाया जा सकता है। हालांकि आप इसके लिए जो मूल्य चुकाते हैं वह ढेर परिचालन में शामिल होता है।


0

ABI- दो बाइनरी प्रोग्राम भागों के बीच रनटाइमApplication Binary Interface में एक मशीन कोड संचार के बारे में है जैसे - एप्लिकेशन, लाइब्रेरी, ओएस ... वर्णन करता है कि ऑब्जेक्ट्स को मेमोरी में कैसे बचाया जाता है और फ़ंक्शन कैसे कहा जाता है ( )ABIcalling convention

एपीआई और एबीआई का एक अच्छा उदाहरण स्विफ्ट भाषा के साथ आईओएस पारिस्थितिकी तंत्र है

  • Application- जब आप विभिन्न भाषाओं का उपयोग करके एक एप्लिकेशन बनाते हैं। उदाहरण के लिए आप एप्लिकेशन का उपयोग करके बना सकते हैं Swiftऔर Objective-C[मिक्सिंग स्विफ्ट और ऑब्जेक्टिव-सी]

  • Application - OS- रनटाइम - Swift runtimeऔर standard librariesओएस के हिस्से हैं और उन्हें प्रत्येक बंडल (जैसे ऐप, फ्रेमवर्क) में शामिल नहीं किया जाना चाहिए। यह ऑब्जेक्टिव-सी के उपयोग की तरह ही है

  • Library- Module Stabilityमामला - संकलन समय - आप एक रूपरेखा आयात करने में सक्षम होंगे जो स्विफ्ट के संकलक के एक और संस्करण के साथ बनाया गया था। इसका मतलब है कि यह एक बंद-स्रोत (प्री-बिल्ड) बाइनरी बनाने के लिए सुरक्षा है जो संकलक के एक अलग संस्करण द्वारा खपत की जाएगी ( .swiftinterfaceजिसका उपयोग किया जाता है .swiftmodule) और आपको नहीं मिलेगा

    Module compiled with _ cannot be imported by the _ compiler
    
  • Library- Library Evolutionमामला

    1. संकलित समय - अगर एक निर्भरता को बदल दिया गया था, तो एक ग्राहक को फिर से तैयार नहीं किया जाना चाहिए।
    2. रनटाइम - एक सिस्टम लाइब्रेरी या एक गतिशील ढांचे को एक नए द्वारा गर्म-स्वैप किया जा सकता है।

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

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