2011-12-14 10 views
10

क्या यह पूरे बाइनरी को निष्पादित करने से पहले स्मृति में कॉपी करता है? मुझे इस प्रश्न में रूचि है और इसे किसी अन्य तरीके से बदलना है। मेरा मतलब है, अगर बाइनरी 100 एम बड़ा है (असंभव प्रतीत होता है), मैं इसे चला सकता हूं जबकि मैं इसे स्मृति में कॉपी कर रहा हूं। क्या यह संभव हो सकता है?जब कोई बाइनरी फ़ाइल चलती है, तो क्या यह एक बार में अपने पूरे बाइनरी डेटा को स्मृति में कॉपी करता है? क्या मैं इसे बदल सकता हूं?

या क्या आप मुझे बता सकते हैं कि यह किस तरह से चलता है? मुझे किस उपकरण की आवश्यकता है?

+3

ओएस सामान्य रूप से इस तरह से एक सौहार्दपूर्ण तरीके से संबंधित है। –

+1

100 एमबी बाइनरी असंभव है? मेरे यहां एकमात्र 500 एलओसी, भारी टेम्पलेट और बूस्टेड सी ++ प्रोग्राम से संकलित 6 एमबी बाइनरी है। मैं शर्त लगाता हूं कि मैं बिना किसी परेशानी के 100 एमबी तक पहुंच सकता हूं। –

+3

कुछ भी असंभव नहीं है! बस एक ग्रहण ग्रहण डेवलपर के संपर्क में रहें, वे आपको सभी चालें सिखाएंगे। – Lundin

उत्तर

24

एप्लिकेशन-स्तरीय प्रोग्रामर के लिए सैद्धांतिक मॉडल ऐसा लगता है कि ऐसा ऐसा है। असल में, सामान्य स्टार्टअप प्रक्रिया (लिनक्स 1.x में कम से कम, मेरा मानना ​​है कि 2.x और 3.x अनुकूलित लेकिन इसी तरह कर रहे हैं) है:

  • गिरी एक प्रक्रिया संदर्भ बनाता है (अधिक या -less, आभासी मशीन)
  • है कि इस प्रक्रिया के संदर्भ में, यह एक आभासी स्मृति मानचित्रण है कि आपके निष्पादन योग्य फ़ाइल
  • के शुरू करने के रैम पते से नक्शे यह मानते हुए कि आप गतिशील रूप से लिंक किए गए हैं (डिफ़ॉल्ट/सामान्य) को परिभाषित करता है, ld.so प्रोग्राम (उदाहरण के लिए /lib/ld-linux.so.2) आपके प्रोग्राम के शीर्षकों में परिभाषित साझा पुस्तकालयों के लिए मेमोरी मैपिंग सेट करता है
  • कर्नेल आपके प्रोग्राम की स्टार्टअप रूटीन में एक jmp करता है (सी प्रोग्राम के लिए, यह crtprec80 जैसा कुछ है, जो main पर कॉल करता है)। चूंकि इसने केवल मैपिंग सेट की है, और वास्तव में किसी भी पेज (*) को लोड नहीं किया है, इसलिए यह सीपीयू की मेमोरी मैनेजमेंट यूनिट से पेज फॉल्ट का कारण बनता है, जो कि कर्नेल में एक बाधा (अपवाद, सिग्नल) है।
  • कर्नेल का पृष्ठ फॉल्ट हैंडलर आपके प्रोग्राम के कुछ अनुभाग को लोड करता है, जिसमें भाग शामिल है जो पेज गलती को रैम में लाता है।
  • जैसे ही आपका प्रोग्राम चलता है, यदि यह वर्चुअल एड्रेस एक्सेस करता है जिसमें रैम बैकिंग नहीं है, तो पेज दोष आते हैं और कर्नेल को प्रोग्राम को संक्षिप्त रूप से निलंबित करने का कारण बनता है, डिस्क से पृष्ठ लोड करें और फिर कार्यक्रम पर वापसी नियंत्रण।यह सभी "निर्देशों के बीच" होता है और आमतौर पर ज्ञानी नहीं होता है।
  • जैसा कि आप malloc/new का उपयोग करते हैं, कर्नेल रैम के पढ़ने-लिखने वाले पृष्ठ (डिस्क बैकिंग फ़ाइलों के बिना) बनाता है और उन्हें आपके वर्चुअल एड्रेस स्पेस में जोड़ता है।
  • यदि आप वर्चुअल मेमोरी मैपिंग में सेट अप मेमोरी स्थान तक पहुंचने का प्रयास करके पेज फॉल्ट फेंकते हैं, तो आपको एक सेगमेंटेशन उल्लंघन उल्लंघन (SIGSEGV) मिलता है, जो आमतौर पर घातक होता है।
  • चूंकि सिस्टम भौतिक RAM से बाहर चला जाता है, रैम के पृष्ठ हटा दिए जाते हैं; अगर वे डिस्क पर पहले से ही कुछ की केवल पढ़ने की प्रतियां हैं (जैसे निष्पादन योग्य, या साझा ऑब्जेक्ट फ़ाइल), तो उन्हें केवल डी-आवंटित किया जाता है और उन्हें उनके स्रोत से पुनः लोड किया जाता है; अगर वे पढ़े गए हैं (जैसे स्मृति "malloc का उपयोग करके" बनाई गई "), वे पृष्ठ फ़ाइल = स्वैप फ़ाइल = स्वैप विभाजन = ऑन-डिस्क वर्चुअल मेमोरी) पर लिखे गए हैं। इन "मुक्त" पृष्ठों तक पहुंचने से एक और पेज फॉल्ट होता है, और वे फिर से लोड हो जाते हैं।

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

तो: प्रभावी रूप से, कर्नेल पहले से ही लोड होने के दौरान आपके प्रोग्राम को चला रहा है (और कभी भी कुछ पेज लोड नहीं कर सकता है, अगर आप कभी भी उस कोड में कूद नहीं जाते हैं/उस डेटा को संदर्भित करते हैं)।

यदि आपका स्टार्टअप विशेष रूप से सुस्त है, तो आप साझा लाइब्रेरी लोड को अनुकूलित करने के लिए prelink सिस्टम देख सकते हैं। इससे ld.so को स्टार्टअप पर (exec और प्रोग्राम के कॉलिंग के साथ-साथ जब आप पहली बार लाइब्रेरी रूटीन कॉल करते हैं) के काम को कम कर देता है।

कभी कभी, स्थिर जोड़ने के लिए एक कार्यक्रम के प्रदर्शन में सुधार कर सकते हैं लेकिन राम का एक प्रमुख कीमत पर - के बाद से अपने पुस्तकालयों साझा नहीं किया जाता है, तो आप डुप्लिकेट बना रहे हैं "अपने libc" साझा libc के साथ ही उस हर दूसरे कार्यक्रम है उदाहरण के लिए, का उपयोग कर। यह आम तौर पर केवल एम्बेडेड सिस्टम में उपयोगी होता है जहां आपका प्रोग्राम मशीन पर अकेले या कम अकेले चल रहा है।

(*) असल में, कर्नेल थोड़ा होशियार है, और आम तौर पर कुछ पृष्ठों प्रीलोड पेज दोष की संख्या को कम करने के लिए होगा, लेकिन सिद्धांत अनुकूलन के ही है, भले ही

+0

मैं महसूस कर रही आप relocator जो एक से अधिक चलाने की आवश्यकता भूल गए मिला एक खाली प्रदर्शन मिला निष्पादन योग्य ब्लॉक स्मृति में लोड किया गया है (http://en.wikipedia.org/wiki/Relocation_%28computer_science%29)। जहाँ तक मुझे इस बार कोड के लोड करने के दौरान होता है और मुझे यकीन है कि अगर 'पृष्ठ गलती' हैंडलर बस इस 'relocator' एल्गोरिथ्म चलेंगे, जबकि कार्यक्रम पहले से ही चल रहा है नहीं कर रहा हूँ पता है। तो मेरी राय में एक निष्पादन ब्लॉक में कम से कम से पहले निष्पादन शुरू होता है एक बार लोड किया जाना है। लेकिन मैं एक 'linux-लोडर' विशेषज्ञ नहीं हूँ ... – LittleFunnyMan

+2

मैं * विश्वास करता हूं * यह सब लिनक्स पर 'ld.so' द्वारा संभाला जाता है, लेकिन मैं जादूगरों के मामलों में दखल नहीं देता हूं :-) ...' थंक 'संचालन में भी बहुत सारे काले जादू शामिल हैं और ऐसे में, पहली बार लाइब्रेरी दिनचर्या का आह्वान किया जाता है ... – BRFennPocock

+0

स्थानांतरण कैसे काम करता है इस बारे में कुछ चर्चा के लिए http://em386.blogspot.com/2006/10/resolving-elf-relocation-name-symbols.html देखें। –

6

नहीं, यह केवल आवश्यक पृष्ठों को स्मृति में लोड करता है। यह मांग पेजिंग है।

मुझे ऐसे उपकरण की जानकारी नहीं है जो वास्तव में वास्तविक समय में दिखाया जा सके, लेकिन आप /proc/xxx/maps पर एक नज़र डाल सकते हैं, जहां xxx आपकी प्रक्रिया का पीआईडी ​​है।

+0

जीनोम में, सिस्टम मॉनिटर मेमोरी मैप्स दिखाएगा। प्रक्रिया → मेमोरी नक्शे पर → राइट क्लिक करें अनुप्रयोग/सिस्टम उपकरण/सिस्टम मॉनिटर → टैब प्रक्रियाओं। खिड़की अक्सर खाली दिखाई देता है जब यह खुलता है, क्योंकि स्क्रॉल बार awkwardly तैनात कर रहे हैं, इसलिए उन्हें देखने अगर आपको लगता है कि आप :-) – BRFennPocock

2

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

यदि आप उत्सुक हैं कि मैप हो जाता है, जैसा कि फेज कहते हैं, तो आप/proc/pid/maps देख सकते हैं।

strace ls 

यह काफी वर्बोज़ है, लेकिन यह आप mmap से कुछ पता चलना चाहिए कि() कहता है, आदि: आप कैसे एक कार्यक्रम भार देखना चाहते हैं, तो आप strace के साथ एक कार्यक्रम चल रहा है, की तरह कोशिश कर सकते हैं