इंपोर्ट लाइब्रेरी कैसे काम करती है? विवरण?


88

मुझे पता है कि यह गीक्स के लिए काफी बुनियादी लग सकता है। लेकिन मैं इसे स्पष्ट करना चाहता हूं।

जब मैं एक Win32 DLL का उपयोग करना चाहता हूं, तो आमतौर पर मैं सिर्फ LoadLibrary () और GetProcAdderss () जैसे API को कॉल करता हूं। लेकिन हाल ही में, मैं DirectX9 के साथ विकास कर रहा हूं, और मुझे d3d9.lib , d3dx9.lib जोड़ना होगा , आदि फ़ाइलों ।

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

इसलिए मेरी वर्तमान समझ यह है कि LIB में विधियों का कार्यान्वयन शामिल है और अंतिम EXE फ़ाइल के भाग के रूप में लिंक समय पर सांख्यिकीय रूप से जुड़ा हुआ है। जबकि DLL रनटाइम पर गतिशील है और अंतिम EXE फ़ाइल का हिस्सा नहीं है।

लेकिन कभी-कभी, कुछ LIB फाइलें DLL फाइल के साथ आती हैं , इसलिए:

  • इन LIB फ़ाइलों के लिए क्या हैं?
  • वे कैसे हासिल करते हैं जो उनके लिए हैं?
  • क्या कोई उपकरण है जो मुझे इन LIB फ़ाइलों के आंतरिक निरीक्षण कर सकता है?

अपडेट १

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

अपडेट २

जैसे RBerteig ने कहा, DLL के साथ पैदा हुई LIB फ़ाइलों में कुछ स्टब कोड हैं। तो कॉलिंग अनुक्रम इस तरह होना चाहिए:

मेरा मुख्य अनुप्रयोग -> LIB में स्टब -> वास्तविक लक्ष्य DLL

तो इन एलआईबी में क्या जानकारी होनी चाहिए? मैं निम्नलिखित के बारे में सोच सकता है:

  • LIB फ़ाइल में संबंधित DLL की फ़ुलपाथ होनी चाहिए; इसलिए DLL को रनटाइम द्वारा लोड किया जा सकता है।
  • प्रत्येक DLL निर्यात विधि के प्रवेश बिंदु के सापेक्ष पते (या फ़ाइल ऑफसेट?) को स्टब में एन्कोड किया जाना चाहिए; तो सही कूद / विधि कॉल किया जा सकता है।

क्या मैं सही हूं? क्या कुछ और है?

BTW: क्या कोई उपकरण है जो एक आयात पुस्तकालय का निरीक्षण कर सकता है? अगर मैं इसे देख सकता हूं, तो अधिक संदेह नहीं होगा।


4
मैं देखता हूं कि किसी ने आपके प्रश्न के अंतिम भाग को संबोधित नहीं किया है, जो उन उपकरणों का संबंध है जो एक आयात पुस्तकालय का निरीक्षण कर सकते हैं। विजुअल C ++ के साथ, इसे करने के कम से कम दो तरीके हैं: lib /list xxx.libऔर link /dump /linkermember xxx.libयह स्टैक ओवरफ्लो प्रश्न देखें ।
एलन

इसके अलावा, और उपयोगिताओं dumpbin -headers xxx.libकी तुलना में कुछ अधिक विस्तृत जानकारी प्रदान करता है । liblink
m_katsifarakis

जवाबों:


102

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

तो रन टाइम पर स्पष्ट रूप से प्रयोग किया जाता है, आप का उपयोग LoadLibrary()और GetProcAddress()मैन्युअल रूप से करने के लिए DLL लोड और कार्यों आप कॉल करने की आवश्यकता की ओर इशारा मिलता है।

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

उन स्टब्स को कहीं से आने की जरूरत है, और Microsoft उपकरण श्रृंखला में वे एक विशेष रूप से .LIB फ़ाइल से आते हैं, जिसे a कहा जाता है आयात लाइब्रेरी । आवश्यक .LIB आमतौर पर DLL के समान ही बनाया जाता है, और DLL से निर्यात होने वाले प्रत्येक फ़ंक्शन के लिए एक स्टब होता है।

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

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

अपडेट करें

यदि आप सिर्फ यह जानने का विरोध नहीं कर सकते हैं कि सभी नट और बोल्ट वास्तव में कहां हैं और वास्तव में क्या चल रहा है, तो मदद करने के लिए MSDN पर हमेशा कुछ होता है। मैट Pietrek के लेख Win32 पोर्टेबल निष्पादन योग्य फ़ाइल प्रारूप में एक में गहराई देखो , EXE फ़ाइल के प्रारूप का बहुत पूरा अवलोकन है और यह कैसे लोड होता है और कैसे चलता है। यह भी .NET को कवर करने के लिए अद्यतन किया गया है और अधिक यह मूल रूप से MSDN मैगज़ीन ca में दिखाई दिया। 2002।

इसके अलावा, यह जानना उपयोगी हो सकता है कि किसी प्रोग्राम द्वारा DLL का सही उपयोग कैसे किया जाए। उस के लिए उपकरण निर्भरता वॉकर, उर्फ ​​depend.exe है। इसका एक संस्करण विजुअल स्टूडियो के साथ शामिल है, लेकिन नवीनतम संस्करण इसके लेखक से http://www.dependencywalker.com/ पर उपलब्ध है । यह उन सभी DLL की पहचान कर सकता है जो लिंक टाइम (शुरुआती लोड और विलंब लोड दोनों) में निर्दिष्ट थे और यह प्रोग्राम को भी चला सकता है और किसी भी अतिरिक्त DLL के लिए देख सकता है जो रन टाइम पर लोड होता है।

अपडेट २

मैंने पूर्व पाठ में से कुछ को फिर से पढ़ने पर स्पष्ट करने के लिए, और MSDN के साथ संगति के लिए कला निहित और स्पष्ट लिंकिंग की शर्तों का उपयोग करने के लिए पुन: तैयार किया है ।

इसलिए, हमारे पास तीन तरीके हैं जो लाइब्रेरी फ़ंक्शंस को प्रोग्राम द्वारा उपयोग किए जाने के लिए उपलब्ध करा सकते हैं। स्पष्ट अनुवर्ती प्रश्न तो यह है: "मैं कैसे रास्ता चुनूं?"

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

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

किसी लाइब्रेरी के लिए DLL में उसके सभी कार्य होते हैं, जो किसी भी क्लाइंट प्रोग्राम द्वारा उपयोग के लिए तैयार हैं। यदि कई प्रोग्राम उस DLL को लोड करते हैं, तो वे सभी इसके कोड पेज साझा कर सकते हैं। हर कोई जीतता है। (ठीक है, जब तक कि आप नए संस्करण के साथ एक DLL अपडेट नहीं करते हैं, लेकिन यह इस कहानी का हिस्सा नहीं है। कहानी के उस पक्ष के लिए Google DLL नर्क।)

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

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

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


3
मेरी पोस्ट को हटाना और इसे अपवर्जित करना, क्योंकि आप चीजों को मेरे द्वारा बेहतर तरीके से समझाते हैं;) अच्छा जवाब।
ereOn

2
@Rerteig: आपके महान उत्तर के लिए धन्यवाद। बस थोड़ा सुधार, यहाँ ( msdn.microsoft.com/en-us/library/9yd93633.aspx ) के अनुसार, DLL के 2 प्रकार के डायनामिक लिंकिंग हैं, लोड-टाइम इम्प्लांट लिंकिंग और रन-टाइम स्पष्ट लिंकिंग । कोई संकलन-समय लिंकिंग नहीं । अब मैं सोच रहा हूं कि पारंपरिक स्टेटिक लिंकिंग (एक * .लिब फाइल से जुड़ा है जिसमें पूर्ण कार्यान्वयन होता है) और लोड-टाइम डायनेमिक लिंकिंग एक DLL (एक आयात पुस्तकालय के माध्यम से) के बीच अंतर क्या है ?
smwikipedia

1
जारी रखें: स्टेटिक लिंकिंग और लोड-टाइम डायनामिक लिंकिंग के पेशेवरों और विपक्ष क्या हैं ? ऐसा लगता है कि ये 2 दृष्टिकोण सभी आवश्यक फाइलों को एक प्रक्रिया की शुरुआत में पता स्थान में लोड करते हैं। हमें उनमें से 2 की आवश्यकता क्यों है? धन्यवाद।
smwikipedia

1
आप शायद एक .lib फ़ाइल के अंदर झांकने के लिए "objdump" जैसे उपकरण का उपयोग कर सकते हैं और यह पता लगा सकते हैं कि यह एक आयात पुस्तकालय है या एक सच्चा स्थिर पुस्तकालय है। लिनक्स पर जब एक विंडोज़ लक्ष्य को संकलित किया जाता है, तो .a फ़ाइलों (.lib फ़ाइलों का mingw संस्करण) पर 'ar' या 'nm' चलाना संभव है और ध्यान दें कि आयात लिब में जेनेरिक .o फ़ाइल नाम और कोई फ़ाइल नहीं है। (सिर्फ एक 'जेएमपी' निर्देश), जबकि स्थिर काम के अंदर बहुत सारे कार्य और कोड होते हैं।
उज्ज्वल

1
छोटे सुधार: आप भी कर सकते हैं परोक्ष रन-टाइम में जोड़ देते हैं। Delay-Loaded DLLs के लिए लिंकर समर्थन इसे विस्तार से बताता है। यदि आप DLL खोज पथ को गतिशील रूप से बदलना चाहते हैं, या इम्पोर्ट रिज़ॉल्यूशन विफलता (नए OS फीचर्स का समर्थन करने के लिए, लेकिन फिर भी पुराने संस्करणों पर चलते हैं), तो यह मददगार है।
IInspectable

5

इन .LIB आयात लाइब्रेरी फ़ाइलों का उपयोग निम्न प्रोजेक्ट प्रॉपर्टी में किया जाता है Linker->Input->Additional Dependencies, जब dll का एक समूह बनाते हैं, जिसे लिंक समय पर अतिरिक्त जानकारी की आवश्यकता होती है, जो आयात लाइब्रेरी द्वारा प्रदान की जाती है ।LIB फ़ाइलें। लिंकर त्रुटियों को प्राप्त नहीं करने के लिए नीचे दिए गए उदाहरण में मुझे dll के A, B, C, और D को उनकी आवश्यक फाइलों के माध्यम से संदर्भित करना होगा। (लिंक करने वाले के लिए इन फ़ाइलों को खोजने के लिए ध्यान दें कि आपको उनकी तैनाती पथ को शामिल करने की आवश्यकता हो सकती है, Linker->General->Additional Library Directoriesअन्यथा आपको प्रदान की गई आवश्यक फ़ाइलों में से किसी को खोजने में असमर्थ होने के बारे में एक बिल्ड त्रुटि मिलेगी।)

लिंकर-> इनपुट-> अतिरिक्त निर्भरता

यदि आपका समाधान सभी गतिशील पुस्तकालयों का निर्माण कर रहा है, तो आप Common Properties->Framework and Referencesसंवाद के तहत उजागर किए गए संदर्भ झंडे के बजाय भरोसा करके इस स्पष्ट निर्भरता विनिर्देश से बचने में सक्षम हो सकते हैं । ये झंडे * .लिब फ़ाइलों का उपयोग करके स्वचालित रूप से आपकी ओर से लिंकिंग करते दिखाई देते हैं। फ्रेमवर्क और संदर्भ

हालांकि यह ऐसा है जैसा कि यह कहता है सामान्य गुण , जो कॉन्फ़िगरेशन या प्लेटफ़ॉर्म विशिष्ट नहीं है। यदि आपको हमारे अनुप्रयोग में मिश्रित बिल्ड परिदृश्य का समर्थन करने की आवश्यकता है, तो हमारे पास स्थैतिक बिल्ड और एक विशेष कॉन्फ़िगरेशन को प्रस्तुत करने के लिए एक बिल्ड कॉन्फ़िगरेशन था, जो असेंबली की एक उप-निर्मित निर्माण को गतिशील पुस्तकालयों के रूप में तैनात किया गया था। मैंने चीजों को बनाने और बाद में चीजों को सरल बनाने के लिए साकार करने के लिए विभिन्न मामलों के तहत सही Use Library Dependency Inputs और Link Library Dependenciesसेट किए गए झंडे का उपयोग किया था, लेकिन जब मेरे कोड को स्टैटिक बिल्ड में पेश किया गया तो मैंने एक टन लिंकर चेतावनी पेश की और स्टैटिक बिल्ड के लिए बिल्ड अविश्वसनीय रूप से धीमा था। मैं इस तरह की चेतावनियों का एक समूह पेश करता हूं ...

warning LNK4006: "bool __cdecl XXX::YYY() already defined in CoreLibrary.lib(JSource.obj); second definition ignored  D.lib(JSource.obj)

और मैं Additional Dependenciesगतिशील बिल्डरों के लिए लिंकर को संतुष्ट करने के लिए मैनुअल विनिर्देशन का उपयोग करके घाव करता हूं , जबकि स्थिर बिल्डरों को एक सामान्य संपत्ति का उपयोग करके खुश नहीं रखता है जो उन्हें धीमा कर देता है। जब मैं डायनेमिक सबसेट का निर्माण करता हूं, तो मैं केवल dll फाइलों को तैनात करता हूं, क्योंकि ये लीब फाइल केवल लिंक टाइम पर उपयोग की जाती हैं, रनटाइम पर नहीं।


3

तीन प्रकार के पुस्तकालय हैं: स्थिर, साझा और गतिशील रूप से भरी हुई पुस्तकालय।

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

गतिशील रूप से लोड किए गए लोग साझा पुस्तकालयों की तरह होते हैं, सिवाय इसके कि जब आप लिखे गए कोड की जरूरत पड़ने पर लोड होते हैं।


@ धन्यवाद ज़ासेक। लेकिन साझा पुस्तकालय के बारे में आपके कथन पर मुझे यकीन नहीं है।
smwikipedia

@smwikipedia: लिनक्स उनके पास है, मैं उनका उपयोग करता हूं, इसलिए वे निश्चित रूप से मौजूद हैं। यह भी पढ़ें: en.wikipedia.org/wiki/Library_(computing)
Zoltán Sz'cs

3
इसका सूक्ष्म अंतर है। साझा और गतिशील लाइब्रेरी दोनों DLL फाइलें हैं। भेद तब होता है जब वे लदे होते हैं। EXE के साथ OS द्वारा साझा लाइब्रेरी लोड की जाती हैं। डायनामिक लाइब्रेरी कोड कॉलिंग LoadLibrary()और संबंधित एपीआई द्वारा लोड की जाती हैं।
RBerteig

मैं [1] से पढ़ता हूं कि DLL Microsoft की साझा लाइब्रेरी अवधारणा का कार्यान्वयन है। [१]: en.wikipedia.org/wiki/Dynamic-link_library#Import_lbooks
smwikipedia

मैं असहमत हूं कि यह एक सूक्ष्म अंतर है, प्रोग्रामिंग दृश्य से यह बहुत बड़ा अंतर पड़ता है कि साझा पुस्तकालय डिनैमली लोड किया गया है या नहीं (यदि यह डायनामिक रूप से लोड किया गया है, तो आपको कार्यों तक पहुंचने के लिए बॉयलरप्लेट कोड जोड़ना होगा)।
Zoltán Sz Augcs

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