2012-06-04 7 views
5

मेरे पास एक डीएलएल है जो लोड करने में 5 से 10 सेकंड लगते हैं, जिसका अर्थ यह है कि मुझे हर बार जब मैं इसे निष्पादित करने वाले निष्पादन योग्य को संकलित करता हूं और चलाता हूं। क्या डीएलएल को स्मृति में लोड करने का कोई तरीका है ताकि हर बार जब मैं इसी निष्पादन योग्य संकलित करता हूं तो इसे तत्काल एक्सेस किया जा सकता है? मैं QT MinGW पर प्रोग्राम संकलित कर रहा हूं, यदि यह प्रासंगिक है।प्रक्रिया छोड़ने के बाद डीएलएल को स्मृति में रखना संभव है?

संपादित करें: अब तक कोई भाग्य नहीं है। किसी अन्य प्रोग्राम पर डीएलएल लोड करना कोई प्रभाव नहीं पड़ता है (मूल प्रोग्राम अभी भी डीएलएल लोड करता है, और ऐसा करने में उतना ही समय लगता है)। मुझे लगता है कि अगर उन्हें किसी अन्य प्रोग्राम में लोड किया गया है तो मुझे डीएलएल और उसके कार्यों को अलग-अलग लोड करने की ज़रूरत है, लेकिन मुझे नहीं पता कि यह कैसे करना है। अभी मैं लोड लाइब्रेरी और GetProcAddress का उपयोग कर रहा हूं।

+3

यह संभवतः लोडिंग-इन-मेमोरी नहीं है, लेकिन डीएलएल के अंदर प्रारंभिक तर्क, जो इतना लंबा समय ले रहा है। स्मृति में डीएलएल को रखना प्रारंभिक विलंब से बच नहीं पाएगा। –

+0

यह सच होने पर दुर्भाग्यपूर्ण होगा। मुझे लगता है कि स्रोत कोड तक पहुंच के बिना मैं कुछ भी नहीं कर सकता हूं? – SharpHawk

+0

आप इसे आउट-ऑफ-प्रोसेस आरपीसी सर्वर में लपेट सकते हैं, लेकिन यह इसका उपयोग कर अक्षमता के लिए तेज़ पुनः कनेक्शन का व्यापार करता है। –

उत्तर

1

सबसे आसान समाधान (MSVC संभालने ++) है DLL देरी से लोड करने के लिए। निश्चित रूप से व्यापार-बंद यह है कि प्रारंभिकizटन अभी भी होना है, लेकिन यह अब आपके कार्यक्रम के अन्य हिस्सों में देरी नहीं करेगा। जैसे आप इसे पृष्ठभूमि धागे पर कर सकते हैं।

+0

इस तथ्य को देखते हुए कि मुझे स्मृति में रहने के लिए डीएलएल नहीं मिल सका, और उस टोटोववो के समाधान का मतलब सस्ते लैपटॉप को धीमा करना होगा, डीएलएल को समानांतर धागे में लोड करना जैसा लगता है जाने के लिए रास्ता। एक ही समाधान को एक संबंधित प्रश्न में प्रस्तुत किया गया था जिसे मैंने यहां StackOverflow पर भी पूछा था। – SharpHawk

1

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

+0

यह निश्चित रूप से उस तरह से प्रकट होता है, इसलिए मैंने अपना "नहीं" संपादित किया। हालांकि मैं उन समाधानों के बारे में असहज महसूस करता हूं। – totowtwo

+0

प्रारंभिक प्रक्रिया डीएलएल से जुड़ी प्रत्येक प्रक्रिया और धागे के लिए होती है। एक सेवा में लोड डीएलएल को केवल फाइल I/O बचाता है। –

+0

क्या आप इसे कैसे करें इस बारे में अधिक जानकारी में जा सकते हैं? जैसा कि यह खड़ा है कि आपका उत्तर ज्यादातर प्रदान किए गए अन्य सुझावों की आलोचना है। – SharpHawk

1

अगर मैं गलत नहीं हूँ, विंडोज स्मृति में DLL का एक उदाहरण रखता है ताकि रखने यह जिंदा काम करना चाहिए:

#include <conio.h> 
#include <windows.h> 

int main() 
    { 
    HMODULE handle=LoadLibrary("yourdll.dll"); 
// Make shure Windows resolves the DLL 
    FARPROC dummy=GetProcAddress(handle,"functionInDll"); 
// The process will now just wait for keyboard input. 
    getch(); 
    CloseHandle(handle); 
    return 0; 
    } 
+0

आप FARPROC डमी = GetProcAddress क्यों करते हैं (हैंडल, "functionInDll"); अगर आप सिर्फ डीएलएल लोड करना चाहते हैं? – rkosegi

+0

एमएचएम, मैंने अपने प्रोग्राम के खुले उदाहरण (डीएलएल के साथ लोड होने के साथ) को छोड़ने का प्रयास किया, लेकिन कार्यक्रम के नए उदाहरणों ने अभी भी डीएलएल लोड करने के लिए वही समय लिया। कार्यों का उपयोग करना हमेशा तात्कालिक होता है। मुझे आश्चर्य है कि समस्या क्या है ... – SharpHawk

2

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

  • उपयोग (आवेदन की स्थापना के दौरान)

    • DLLs
    • DLLs और exe बंधन का अनूठा आधार पतों की चयन: इस तरह की समस्याएं आम तौर पर तीन तकनीक के उपयोग के साथ हल से होगा तकनीक
    • एक छोटे से DllMain

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

    समस्या को समझने के लिए आपको पता होना चाहिए कि निष्पादन योग्य या डीएलएल कैसे लोड किया जाएगा। सबसे पहले EXE या DLL स्मृति में मैप किया जाएगा। Memory mapped file (सेक्शन) बनाया जाएगा जो EXE/DLL को इंगित करता है। तो आपके पास प्रक्रिया में कुछ पते होंगे जो एक्सेस EXE/DLL फ़ाइल के अनुरूप होंगे। यदि आप डीएलएल को लिंक करते हैं तो आप मूल पता चुन सकते हैं। यदि पता पता स्थान में पते का उपयोग नहीं किया गया है तो कुछ भी नहीं किया जाएगा। यदि कोड की पहली पंक्ति का उपयोग किया जाएगा (आप डीएलएल से कुछ फ़ंक्शन कॉल करते हैं) तो प्रयुक्त पते के पास मेमोरी 8K का पृष्ठ फ़ाइल से स्मृति में लोड किया जाएगा। यदि दो प्रक्रियाएं एक ही डीएलएल का उपयोग करती हैं तो कोड के लिए भौतिक स्मृति प्रक्रियाओं के बीच साझा की जाएगी। यहां तक ​​कि यदि आप प्रारंभिक चर रखते हैं तो वेरिएबल वाले पेज को चर के पहले परिवर्तन तक साझा किया जाएगा। संशोधन पर प्रक्रिया के लिए स्मृति के पृष्ठ की प्रतिलिपि बनाई जाएगी जिसने संशोधन किया था।

    प्रक्रिया में डीएलएल लोड होने के बाद कॉलर के कुछ छोटे हिस्सों (उदाहरण के लिए EXE) को डीएलएल से उपयोग किए गए कार्यों के वास्तविक पते को शामिल करने के लिए संशोधित किया जाना चाहिए। डीएलएल के साथ ऐसा ही किया जाएगा जो किसी अन्य डीएलएल से कार्यों का उपयोग करता है।

    सब कुछ सही ध्वनि, लेकिन आप DLL संकलन के दौरान किसी भी लिंकर विकल्प सेट नहीं है (यदि आप --image-base या --enable-auto-image-base लिंकर विकल्प का उपयोग नहीं करते हैं) आप के लिए डिफ़ॉल्ट मान एक ही आधार पते के साथ अपने सभी DLLs होगा (लिंकर)। तो पहले डीएलएल पते पर लोड किया जा सकता है। दूसरे डीएलएल को लोड करने के दौरान जो (या कुछ ओवरलैप्ड एड्रेस) से जुड़े होते हैं, डीएलएल का स्थानांतरण किया जाएगा। स्थानांतरण के दौरान डीएलएल सिल्ल का कोड संशोधित किया जाएगा और इसलिए 1) डीएलएल की लोडिंग धीरे-धीरे 2 होगी) कोड की संशोधित प्रति प्रक्रिया में बनाई जाएगी (जिसमें डीएलएल द्वारा उपयोग की जाने वाली मेमोरी शामिल है) 3) संशोधित प्रति डीएलएल के कई उदाहरणों के बीच साझा नहीं किया जाएगा (भले ही सभी उदाहरण एक ही तरीके से संशोधित किए जाएंगे)।

    उदाहरण के लिए मैं आपको सबसे पहले Process Explorer का उपयोग करने की सलाह देता हूं ताकि यह सत्यापित किया जा सके कि आपके आवेदन में कौन से डीएलएल स्थानांतरित किए जाएंगे। आपको "व्यू"/"लोअर पेन व्यू" मेनू में "डीएलएल" विकल्प चुनना चाहिए और "विकल्प" मेनू के "हाइलाइटिंग कॉन्फ़िगर करें" में "रिलायंस डीएलएल" चेकबॉक्स का चयन करना चाहिए। आप अतिरिक्त रूप से अनुकूलित कर सकते हैं कि प्रत्येक डीएलएल के बारे में कौन सी जानकारी प्रदर्शित की जाएगी। आप नीचे दिए गए की तरह अधिक जानकारी अधिक धीमी गति से कार्यक्रम लोड किया जाएगा देखेंगे और अधिक पता स्थान आपके आवेदन के उदाहरण के बीच या जो एक ही DLL का उपयोग विभिन्न अनुप्रयोगों के बीच साझा नहीं किया जाएगा:

    enter image description here

    में उपरोक्त उदाहरण में आप देखते हैं कि पेड़ लेनोवो डीएलएल TPOSDSVC.dll, HKVOLKEY.dll और TPLHMM.dll समान आधार पते 0x10000000 से जुड़े हुए हैं और केवल एक डीएलएल (TPOSDSVC.dll) पते पर लोड किया जाएगा। दो अन्य डीएलएल को फिर से स्थानांतरित करना होगा।

    मैं इस विषय के बारे में यहां एक पुस्तक नहीं लिख सकता। मैं आपको स्थानांतरण आवेदन पर अपने आवेदन की जांच करने की सलाह देता हूं। आप या तो लिंकर विकल्प (--image-base या --enable-auto-image-base का उपयोग कर सकते हैं जो आपको चाहिए) का उपयोग कर सकते हैं। पीई छवि की जांच के लिए आप dumpbin.exe टूल (विजुअल स्टूडियो से भी मुफ्त संस्करण में) का उपयोग कर सकते हैं।

    अपने सभी DLLs के बाद आप EXE और उसके आश्रित DLLs के लिए अपने DLLs बाध्य करने के लिए विकल्प -u साथ एक और उपकरण bind.exe उपयोग कर सकते हैं अद्वितीय आधार पता होगा। यह अतिरिक्त रूप से स्मृति आकार को कम करेगा और एप्लिकेशन के प्रारंभिक समय में सुधार करेगा। यह आपके डीएलएल और EXE के IMAGE_DIRECTORY_ENTRY_IMPORT और IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT अपडेट करेगा (the answer देखें)। Bind.exe आंतरिक रूप से BindImageEx एपीआई का उपयोग करता है। कई विंडोज इंस्टालर सेटअप EXE और DLLs के इंस्टॉलेशन के अंत में बाध्यकारी बनाने के लिए BindImage एक्शन और BindImage तालिका का उपयोग करते हैं।

    डीएलएल और EXE के आकार को कम करने के लिए आप अन्य तकनीकों (here देखें) पर विचार कर सकते हैं।

    मुझे नहीं पता कि आप मिनजीडब्ल्यू में देरी-लोड तकनीक का उपयोग कैसे कर सकते हैं, लेकिन यह निश्चित रूप से संभव होना चाहिए। विजुअल स्टूडियो आपको दो चरणों को करने की आवश्यकता है: Delayimp.lib अतिरिक्त लाइब्रेरी के रूप में शामिल करें और /DELAYLOAD विकल्प (here देखें) निर्दिष्ट करने के लिए कि डीएलएल से सीधे उपयोग के पहले उपयोग पर लोड किया जाना चाहिए। बहुत उपयोगी टूल Dependency Walker का उपयोग करके आप देख सकते हैं कि अधिकांश मानक माइक्रोसॉफ्ट डीएलएल तकनीक का उपयोग करते हैं। यदि आप तकनीक का उपयोग भी करेंगे तो आप अपने आवेदन के प्रारंभ समय में सुधार कर सकते हैं और उपयोग की गई स्मृति को कम कर सकते हैं।

  • संबंधित मुद्दे