c# - 'स्थैतिक रूप से जुड़े' और 'गतिशील रूप से जुड़े' का क्या अर्थ है?




c++ linker (4)

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

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

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

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


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

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

#include <stdio.h>

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

सी प्रोग्राम को गतिशील रूप से लिंक करें

gcc simpleprog.c -o simpleprog

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

file simpleprog 

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

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

इसके बजाए इस बार कार्यक्रम को स्थिर रूप से लिंक करें:

gcc simpleprog.c -static -o simpleprog

इस स्थाई रूप से जुड़ी बाइनरी पर चलने वाली फ़ाइल दिखाएगी:

file simpleprog 

"सरलप्रोग: ईएलएफ 64-बिट एलएसबी निष्पादन योग्य, x86-64, संस्करण 1 (जीएनयू / लिनक्स), जीएनयू / लिनक्स 2.6.26 के लिए स्थिर रूप से जुड़ा हुआ, बिल्डआईडी [sha1] = 0x8c0b12250801c5a7c7434647b7dc65a644d6132b, छीन नहीं"

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

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

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

strace ./simpleprog

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


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

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

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

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

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

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

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

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

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


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







dynamic-linking