जवाबों:
स्रोत कोड (आप जो लिखते हैं) से निष्पादन योग्य कोड (जो आप चलाते हैं) में प्राप्त करने में दो चरणों (ज्यादातर मामलों में, व्याख्या किए गए कोड पर छूट) हैं।
पहला संकलन है जो स्रोत कोड को ऑब्जेक्ट मॉड्यूल में बदल देता है।
दूसरा, जोड़ने वाला, एक निष्पादन योग्य बनाने के लिए ऑब्जेक्ट मॉड्यूल को एक साथ जोड़ता है।
अन्य चीजों के अलावा, तीसरे पक्ष के पुस्तकालयों को आपके निष्पादन योग्य में उनके स्रोत कोड (जैसे डेटाबेस एक्सेस, नेटवर्क संचार और ग्राफिकल यूजर इंटरफेस के लिए पुस्तकालय), या विभिन्न भाषाओं में कोड संकलन के लिए देखे बिना आपके निष्पादन में शामिल होने की अनुमति दी जाती है। सी और उदाहरण के लिए विधानसभा कोड) और फिर उन सभी को एक साथ जोड़ना।
जब आप किसी फ़ाइल को निष्पादन योग्य रूप से लिंक करते हैं, तो उस फ़ाइल की सामग्री लिंक समय पर शामिल हो जाती है। दूसरे शब्दों में, फ़ाइल की सामग्री को भौतिक रूप से निष्पादन योग्य में डाला जाता है जिसे आप चलाएंगे।
जब आप गतिशील रूप से लिंक करते हैं , तो फ़ाइल में एक पॉइंटर को जोड़ा जा रहा है (फ़ाइल का फ़ाइल नाम, उदाहरण के लिए) निष्पादन योग्य में शामिल किया गया है और उक्त फ़ाइल की सामग्री लिंक समय पर शामिल नहीं हैं। यह केवल तब होता है जब आप बाद में निष्पादन योग्य चलाते हैं कि इन गतिशील रूप से लिंक की गई फ़ाइलों को खरीदा जाता है और वे केवल निष्पादन योग्य की मेमोरी मेमोरी में खरीदी जाती हैं, न कि डिस्क पर।
यह मूल रूप से आस्थगित लिंकिंग की एक विधि है। वहाँ एक और भी अधिक आस्थगित विधि (कुछ प्रणालियों पर देर से बाध्यकारी कहा जाता है) जो गतिशील रूप से जुड़ी हुई फ़ाइल में नहीं लाएगी जब तक कि आप वास्तव में इसके भीतर एक फ़ंक्शन को कॉल करने का प्रयास न करें।
स्टेटिकली लिंक्ड फाइल्स को लिंक टाइम पर एक्ज़ीक्यूटेबल के लिए 'लॉक' किया जाता है ताकि वे कभी भी न बदले। एक निष्पादन योग्य द्वारा संदर्भित गतिशील रूप से लिंक की गई फ़ाइल डिस्क पर फ़ाइल को बदलकर बदल सकती है।
यह कोड को फिर से लिंक किए बिना कार्यक्षमता को अपडेट करने की अनुमति देता है; लोडर फिर से हर बार जब आप इसे चलाते हैं।
यह अच्छा और बुरा दोनों है - एक तरफ, यह आसान अपडेट और बग फिक्स की अनुमति देता है, दूसरी तरफ यह प्रोग्राम को काम करने के लिए परेशान कर सकता है अगर अपडेट असंगत हैं - यह कभी-कभी खतरनाक "डीएलएल नरक" के लिए जिम्मेदार है कि कुछ लोग उस एप्लिकेशन में उल्लेख किया जा सकता है यदि आप एक गतिशील रूप से लिंक किए गए पुस्तकालय को बदलते हैं जो संगत नहीं है (डेवलपर्स जो ऐसा करते हैं, उन्हें नीचे शिकार किया जाना चाहिए और जिस तरह से गंभीर रूप से दंडित किया जाना चाहिए)।
एक उदाहरण के रूप में , आइए 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 में ड्रॉप कर सकता है। जैसा कि पहले कहा गया है, इसके फायदे और नुकसान दोनों हैं।
.dll
या .so
विस्तार हो सकता है ) - - एक सटीक विवरण होने के बजाय अवधारणाओं को समझाने के रूप में जवाब के बारे में सोचो । और, पाठ के अनुसार, यह एक उदाहरण है जो केवल सी रनटाइम फ़ाइलों के लिए स्थिर और गतिशील लिंकिंग दिखा रहा है, हां, यही `crt उन सभी में इंगित करता है।
मुझे लगता है कि इस सवाल का एक अच्छा जवाब यह बताने के लिए चाहिए कि लिंकिंग क्या है ।
जब आप कुछ C कोड संकलित करते हैं (उदाहरण के लिए), इसका अनुवाद मशीनी भाषा में किया जाता है। बस बाइट्स का एक क्रम, जो जब चलता है, तो प्रोसेसर को जोड़ने, घटाने, तुलना करने का कारण बनता है, "गोटो", मेमोरी पढ़ें, मेमोरी लिखें, उस तरह की चीज। यह सामान ऑब्जेक्ट (.o) फ़ाइलों में संग्रहीत है।
अब, बहुत समय पहले, कंप्यूटर वैज्ञानिकों ने इस "सबरूटीन" चीज का आविष्कार किया था। निष्पादित-यह-हिस्सा के- कोड और वापसी-यहाँ। यह महसूस करने से बहुत पहले नहीं था कि सबसे उपयोगी सबरूटीन को एक विशेष स्थान पर संग्रहीत किया जा सकता है और किसी भी प्रोग्राम द्वारा उपयोग किया जा सकता है जिनकी उन्हें आवश्यकता है।
अब शुरुआती दिनों में प्रोग्रामर को मेमोरी एड्रेस में पंच करना होगा कि ये सबरूटीन किस स्थान पर स्थित थे। कुछ इस तरह CALL 0x5A62
। यह थकाऊ और समस्याग्रस्त था उन स्मृति पतों को कभी भी बदलने की आवश्यकता है।
तो, प्रक्रिया स्वचालित थी। आप एक प्रोग्राम लिखते हैं जो कॉल करता है printf()
, और कंपाइलर को मेमोरी एड्रेस का पता नहीं होता है printf
। तो संकलक सिर्फ लिखते हैं CALL 0x0000
, और वस्तु फ़ाइल कह के लिए एक नोट कहते हैं "की स्मृति स्थान के साथ इस 0x0000 बदलना होगा printf "।
स्टेटिक लिंकेज का अर्थ है कि लिंकर प्रोग्राम (GNU वन को ld कहा जाता है ) printf
आपकी निष्पादन योग्य फ़ाइल में सीधे मशीन कोड जोड़ता है , और 0x0000 के पते में परिवर्तन करता है printf
। यह तब होता है जब आपका निष्पादन योग्य बनाया जाता है।
डायनेमिक लिंकेज का मतलब है कि उपरोक्त कदम ऐसा नहीं है। निष्पादन योग्य फ़ाइल में अभी भी एक नोट है जो कहता है "प्रिंटफ की मेमोरी स्थान के साथ 0x000 को बदलना होगा"। ऑपरेटिंग सिस्टम के लोडर को प्रिंटफ कोड खोजने, मेमोरी में लोड करने और CALL एड्रेस को सही करने के लिए, हर बार प्रोग्राम को चलाने की आवश्यकता होती है ।
कार्यक्रमों के लिए कुछ कार्यों को कॉल करना आम है जो स्टेटिकली लिंक्ड होंगे (मानक लाइब्रेरी फ़ंक्शंस printf
आमतौर पर स्टेटिकली लिंक्ड होते हैं) और अन्य फ़ंक्शंस जो डायनेमिक लिंक्ड हैं। स्थिर लोग निष्पादन योग्य के "भाग" बन जाते हैं और गतिशील वाले "में शामिल होते हैं" जब निष्पादन योग्य चलाया जाता है।
दोनों तरीकों के फायदे और नुकसान हैं, और ऑपरेटिंग सिस्टम के बीच अंतर हैं। लेकिन जब से तुमने नहीं पूछा, मैं इसे यहाँ समाप्त करूँगा।
ld
प्रलेखन को देखना चाहते हैं ।
संकलित समय में सांख्यिकीय रूप से जुड़े पुस्तकालय जुड़े हुए हैं। डायनामिकली लिंक्ड लाइब्रेरियों को रन टाइम पर लोड किया जाता है। स्टेटिक लिंकिंग आपके एक्जीक्यूटेबल में लाइब्रेरी बिट को बेक करता है। लाइब्रेरी के संदर्भ में डायनेमिक लिंकिंग केवल बेक करता है; डायनेमिक लाइब्रेरी के लिए बिट्स कहीं और मौजूद हैं और बाद में इन्हें स्वैप किया जा सकता है।
क्योंकि उपरोक्त में से कोई भी पोस्ट वास्तव में यह नहीं दर्शाती है कि किसी चीज़ को स्टेटिकली लिंक कैसे करें और देखें कि आपने इसे सही तरीके से किया है इसलिए मैं इस मुद्दे को संबोधित करूंगा:
एक साधारण सी कार्यक्रम
#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
डायनामिकली लिंक्ड प्रोग्राम के आउटपुट से तुलना करें और आप देखेंगे कि स्टेटिकली लिंक्ड वर्जन का स्ट्रेस बहुत कम है!
(मैं सी # नहीं जानता, लेकिन यह वीएम भाषा के लिए एक स्थिर लिंकिंग अवधारणा के लिए दिलचस्प है)
डायनेमिक लिंकिंग में यह जानना शामिल है कि एक आवश्यक कार्यक्षमता कैसे प्राप्त की जाए जो आपके कार्यक्रम से केवल एक संदर्भ है। आप फ़ाइलटाइम, नेटवर्क या संकलित कोड कैश पर कोड के एक टुकड़े के लिए भाषा रनटाइम या ओएस खोज करते हैं, संदर्भ से मेल खाते हैं, और फिर इसे मेमोरी में आपके प्रोग्राम इमेज में स्थानांतरित करने के लिए कई उपाय करते हैं, जैसे कि स्थानांतरण। वे सभी रनटाइम पर किए जाते हैं। यह मैन्युअल रूप से या कंपाइलर द्वारा किया जा सकता है। गड़बड़ करने के जोखिम के साथ अद्यतन करने की क्षमता है (अर्थात्, डीएलएल नरक)।
स्टेटिक लिंकिंग संकलन समय पर किया जाता है, आप संकलक को बताते हैं कि सभी कार्यात्मक भाग कहाँ हैं और इसे उन्हें एकीकृत करने के लिए निर्देश दें। कोई खोज नहीं है, कोई अस्पष्टता नहीं है, एक recompile के बिना अपडेट करने की क्षमता नहीं है। आपकी सभी निर्भरताएं शारीरिक रूप से आपकी प्रोग्राम छवि के साथ हैं।