'स्टैटिकली लिंक्ड' और 'डायनेमिकली लिंक्ड' का क्या मतलब है?


229

मैं अक्सर C , C ++ या C # में लिखे गए कोड के संदर्भ में 'स्टेटिकली लिंक्ड' और 'डायनेमिकली लिंक्ड' शब्द सुनता हूं । वे क्या हैं, वास्तव में वे किस बारे में बात कर रहे हैं और वे क्या लिंक दे रहे हैं?

जवाबों:


445

स्रोत कोड (आप जो लिखते हैं) से निष्पादन योग्य कोड (जो आप चलाते हैं) में प्राप्त करने में दो चरणों (ज्यादातर मामलों में, व्याख्या किए गए कोड पर छूट) हैं।

पहला संकलन है जो स्रोत कोड को ऑब्जेक्ट मॉड्यूल में बदल देता है।

दूसरा, जोड़ने वाला, एक निष्पादन योग्य बनाने के लिए ऑब्जेक्ट मॉड्यूल को एक साथ जोड़ता है।

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

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

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

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

स्टेटिकली लिंक्ड फाइल्स को लिंक टाइम पर एक्ज़ीक्यूटेबल के लिए 'लॉक' किया जाता है ताकि वे कभी भी न बदले। एक निष्पादन योग्य द्वारा संदर्भित गतिशील रूप से लिंक की गई फ़ाइल डिस्क पर फ़ाइल को बदलकर बदल सकती है।

यह कोड को फिर से लिंक किए बिना कार्यक्षमता को अपडेट करने की अनुमति देता है; लोडर फिर से हर बार जब आप इसे चलाते हैं।

यह अच्छा और बुरा दोनों है - एक तरफ, यह आसान अपडेट और बग फिक्स की अनुमति देता है, दूसरी तरफ यह प्रोग्राम को काम करने के लिए परेशान कर सकता है अगर अपडेट असंगत हैं - यह कभी-कभी खतरनाक "डीएलएल नरक" के लिए जिम्मेदार है कि कुछ लोग उस एप्लिकेशन में उल्लेख किया जा सकता है यदि आप एक गतिशील रूप से लिंक किए गए पुस्तकालय को बदलते हैं जो संगत नहीं है (डेवलपर्स जो ऐसा करते हैं, उन्हें नीचे शिकार किया जाना चाहिए और जिस तरह से गंभीर रूप से दंडित किया जाना चाहिए)।


एक उदाहरण के रूप में , आइए main.cस्थैतिक और गतिशील लिंकिंग के लिए अपनी फ़ाइल संकलित करने वाले उपयोगकर्ता के मामले को देखें।

Phase     Static                    Dynamic
--------  ----------------------    ------------------------
          +---------+               +---------+
          | main.c  |               | main.c  |
          +---------+               +---------+
Compile........|.........................|...................
          +---------+ +---------+   +---------+ +--------+
          | main.o  | | crtlib  |   | main.o  | | crtimp |
          +---------+ +---------+   +---------+ +--------+
Link...........|..........|..............|...........|.......
               |          |              +-----------+
               |          |              |
          +---------+     |         +---------+ +--------+
          |  main   |-----+         |  main   | | crtdll |
          +---------+               +---------+ +--------+
Load/Run.......|.........................|..........|........
          +---------+               +---------+     |
          | main in |               | main in |-----+
          | memory  |               | memory  |
          +---------+               +---------+

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

गतिशील मामले में, मुख्य कार्यक्रम सी रनटाइम आयात पुस्तकालय (ऐसा कुछ है जो घोषित करता है कि गतिशील पुस्तकालय में क्या है लेकिन वास्तव में परिभाषित नहीं है) के साथ जुड़ा हुआ है । यह लिंकर को लिंक करने की अनुमति देता है भले ही वास्तविक कोड गायब हो।

फिर, रनटाइम पर, ऑपरेटिंग सिस्टम लोडर मुख्य प्रोग्राम को सी रनटाइम DLL (डायनेमिक लिंक लाइब्रेरी या साझा लाइब्रेरी या अन्य नामकरण) के साथ देर से लिंक करता है।

सी रनटाइम का मालिक अपडेट या बग फिक्स प्रदान करने के लिए किसी भी समय एक नए DLL में ड्रॉप कर सकता है। जैसा कि पहले कहा गया है, इसके फायदे और नुकसान दोनों हैं।


11
कृपया मुझे सही करें अगर मैं गलत हूं, लेकिन विंडोज पर, सॉफ़्टवेयर को अपने स्वयं के पुस्तकालयों को इंस्टॉल के साथ शामिल करना पड़ता है, भले ही वे गतिशील रूप से जुड़े हों। पैकेज प्रबंधक के साथ कई लिनक्स प्रणालियों पर, कई गतिशील रूप से जुड़े पुस्तकालयों ("साझा ऑब्जेक्ट") वास्तव में सॉफ्टवेयर के बीच साझा किए जाते हैं।
पॉल फिशर

6
@PaFF: विंडोज कॉमन कंट्रोल्स, डायरेक्टएक्स, .NET जैसी चीजें और बहुत सारे ऐप्स के साथ जहाज पर, जबकि लिनक्स पर, आप एपेट या यम या कुछ और जैसे कि निर्भरता को प्रबंधित करने के लिए उपयोग करते हैं - तो आप उस अर्थ में सही हैं । विन ऐप्स जो अपने खुद के कोड को DLL के रूप में शिप करते हैं, उन्हें साझा नहीं करते हैं।
paxdiablo

31
उन लोगों के लिए नरक के नौवें चक्र में एक विशेष स्थान आरक्षित है जो अपनी DLL को अपडेट करते हैं और पिछड़े संगतता को तोड़ते हैं। हां, यदि इंटरफेस गायब हो जाते हैं या संशोधित होते हैं, तो डायनेमिक लिंकिंग एक ढेर में गिर जाएगी। इसलिए ऐसा नहीं किया जाना चाहिए। सभी तरीकों से अपने DLL में एक फ़ंक्शन 2 () जोड़ें, लेकिन फ़ंक्शन () का उपयोग न करें यदि लोग इसका उपयोग कर रहे हैं। सबसे अच्छा तरीका है कि फ़ंक्शन () को इस तरह से फिर से लिखना है, इसे फ़ंक्शन 2 () कहते हैं, लेकिन फ़ंक्शन के हस्ताक्षर को नहीं बदलते ()।
पाक्सिडाब्लो

1
@Paul फिशर, मुझे पता है कि यह देर हो चुकी है ... लेकिन लाइब्रेरी जो कि Windows DLL के साथ जहाज है, पूरी लाइब्रेरी नहीं है, यह सिर्फ स्टब्स का एक गुच्छा है जो लिंकर को बताता है कि DLL में क्या है। लिंकर फिर DLL को लोड करने के लिए जानकारी को .exe में स्वचालित रूप से डाल सकता है, और प्रतीकों को अपरिभाषित नहीं दिखाता है।
मार्क रैनसम

1
@Santropedro, आप सभी गणनाओं पर सही हैं, यह अर्थ, आयात और DLL नामों का अर्थ बताता है। प्रत्यय केवल इतना है कि उसमें बहुत अधिक पढ़ा नहीं है (उदाहरण के लिए, DLL एक .dllया .soविस्तार हो सकता है ) - - एक सटीक विवरण होने के बजाय अवधारणाओं को समझाने के रूप में जवाब के बारे में सोचो । और, पाठ के अनुसार, यह एक उदाहरण है जो केवल सी रनटाइम फ़ाइलों के लिए स्थिर और गतिशील लिंकिंग दिखा रहा है, हां, यही `crt उन सभी में इंगित करता है।
पैक्सिडाब्लो

221

मुझे लगता है कि इस सवाल का एक अच्छा जवाब यह बताने के लिए चाहिए कि लिंकिंग क्या है

जब आप कुछ C कोड संकलित करते हैं (उदाहरण के लिए), इसका अनुवाद मशीनी भाषा में किया जाता है। बस बाइट्स का एक क्रम, जो जब चलता है, तो प्रोसेसर को जोड़ने, घटाने, तुलना करने का कारण बनता है, "गोटो", मेमोरी पढ़ें, मेमोरी लिखें, उस तरह की चीज। यह सामान ऑब्जेक्ट (.o) फ़ाइलों में संग्रहीत है।

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

अब शुरुआती दिनों में प्रोग्रामर को मेमोरी एड्रेस में पंच करना होगा कि ये सबरूटीन किस स्थान पर स्थित थे। कुछ इस तरह CALL 0x5A62। यह थकाऊ और समस्याग्रस्त था उन स्मृति पतों को कभी भी बदलने की आवश्यकता है।

तो, प्रक्रिया स्वचालित थी। आप एक प्रोग्राम लिखते हैं जो कॉल करता है printf(), और कंपाइलर को मेमोरी एड्रेस का पता नहीं होता है printf। तो संकलक सिर्फ लिखते हैं CALL 0x0000, और वस्तु फ़ाइल कह के लिए एक नोट कहते हैं "की स्मृति स्थान के साथ इस 0x0000 बदलना होगा printf "।

स्टेटिक लिंकेज का अर्थ है कि लिंकर प्रोग्राम (GNU वन को ld कहा जाता है ) printfआपकी निष्पादन योग्य फ़ाइल में सीधे मशीन कोड जोड़ता है , और 0x0000 के पते में परिवर्तन करता है printf। यह तब होता है जब आपका निष्पादन योग्य बनाया जाता है।

डायनेमिक लिंकेज का मतलब है कि उपरोक्त कदम ऐसा नहीं है। निष्पादन योग्य फ़ाइल में अभी भी एक नोट है जो कहता है "प्रिंटफ की मेमोरी स्थान के साथ 0x000 को बदलना होगा"। ऑपरेटिंग सिस्टम के लोडर को प्रिंटफ कोड खोजने, मेमोरी में लोड करने और CALL एड्रेस को सही करने के लिए, हर बार प्रोग्राम को चलाने की आवश्यकता होती है

कार्यक्रमों के लिए कुछ कार्यों को कॉल करना आम है जो स्टेटिकली लिंक्ड होंगे (मानक लाइब्रेरी फ़ंक्शंस printfआमतौर पर स्टेटिकली लिंक्ड होते हैं) और अन्य फ़ंक्शंस जो डायनेमिक लिंक्ड हैं। स्थिर लोग निष्पादन योग्य के "भाग" बन जाते हैं और गतिशील वाले "में शामिल होते हैं" जब निष्पादन योग्य चलाया जाता है।

दोनों तरीकों के फायदे और नुकसान हैं, और ऑपरेटिंग सिस्टम के बीच अंतर हैं। लेकिन जब से तुमने नहीं पूछा, मैं इसे यहाँ समाप्त करूँगा।


4
मैंने भी किया था, हालाँकि मुझे केवल 1 उत्तर चुनना है।
UnkwnTech

1
आर्टेलियस, मैं आपके स्पष्टीकरण के बारे में गहराई से कुछ देख रहा हूं कि ये पागल निम्न स्तर की चीजें कैसे काम करती हैं। उपरोक्त बातों के बारे में अनिश्चित ज्ञान प्राप्त करने के लिए हमें किन पुस्तकों को पढ़ना चाहिए। धन्यवाद।
महेश १

1
क्षमा करें, मैं किसी भी पुस्तक का सुझाव नहीं दे सकता। आपको पहले विधानसभा भाषा सीखनी चाहिए। तब विकिपीडिया ऐसे विषयों का एक सभ्य अवलोकन दे सकता है। आप GNU ldप्रलेखन को देखना चाहते हैं ।
आर्टेलियस

31

संकलित समय में सांख्यिकीय रूप से जुड़े पुस्तकालय जुड़े हुए हैं। डायनामिकली लिंक्ड लाइब्रेरियों को रन टाइम पर लोड किया जाता है। स्टेटिक लिंकिंग आपके एक्जीक्यूटेबल में लाइब्रेरी बिट को बेक करता है। लाइब्रेरी के संदर्भ में डायनेमिक लिंकिंग केवल बेक करता है; डायनेमिक लाइब्रेरी के लिए बिट्स कहीं और मौजूद हैं और बाद में इन्हें स्वैप किया जा सकता है।


16

क्योंकि उपरोक्त में से कोई भी पोस्ट वास्तव में यह नहीं दर्शाती है कि किसी चीज़ को स्टेटिकली लिंक कैसे करें और देखें कि आपने इसे सही तरीके से किया है इसलिए मैं इस मुद्दे को संबोधित करूंगा:

एक साधारण सी कार्यक्रम

#include <stdio.h>

int main(void)
{
    printf("This is a string\n");
    return 0;
}

सी प्रोग्राम को डायनामिकली लिंक करें

gcc simpleprog.c -o simpleprog

और fileबाइनरी पर चलाएं :

file simpleprog 

और यह दिखाएगा कि यह गतिशील रूप से कुछ लाइनों के साथ जुड़ा हुआ है:

"simpleprog: ELF 64-बिट LSB निष्पादन योग्य, x86-64, संस्करण 1 (SYSV), गतिशील रूप से जुड़ा हुआ है (जीएनयू / लिनक्स 2.6.26 के लिए उपयोग किया जाता है), बिल्डआईडी [sha1] = 0x7155757268a8b04f686809d90d1c0d75c602828ff0f

इसके बजाय हमें इस बार स्टेटिकली लिंक दें:

gcc simpleprog.c -static -o simpleprog

इस स्टैटिकली लिंक्ड बाइनरी पर रनिंग फ़ाइल दिखाई देगी:

file simpleprog 

"simpleprog: ELF 64-बिट LSB निष्पादन योग्य, x86-64, संस्करण 1 (GNU / Linux), स्टेटिक रूप से जुड़ा हुआ, GNU / Linux के लिए 2.6.26, BuildID [sha1] = 0x8c0b1220801c5a7c74347b7dc65a644d6132b, छीन नहीं लिया गया।

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

सौभाग्य से कई एम्बेडेड सी लाइब्रेरी जैसे muslलगभग सभी के लिए स्थैतिक लिंकिंग विकल्प प्रदान करते हैं यदि उनके सभी लाइब्रेरी नहीं हैं।

अब straceआपके द्वारा बनाया गया बाइनरी और आप देख सकते हैं कि प्रोग्राम शुरू होने से पहले कोई लाइब्रेरी एक्सेस नहीं है:

strace ./simpleprog

अब straceडायनामिकली लिंक्ड प्रोग्राम के आउटपुट से तुलना करें और आप देखेंगे कि स्टेटिकली लिंक्ड वर्जन का स्ट्रेस बहुत कम है!


2

(मैं सी # नहीं जानता, लेकिन यह वीएम भाषा के लिए एक स्थिर लिंकिंग अवधारणा के लिए दिलचस्प है)

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

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

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